Troubleshooting

Glasses won't connect

Fix common first-connection failures on Meta Ray-Ban — no pairing dialog, session won't start, the DAT auth callback never fires, or an immediate disconnect.

Your app calls glasses.connection.connect() (or the user taps connect on ExtentosConnectionPage) and nothing usable happens — no pairing prompt, a session that never reaches Active, an auth callback that never returns, or a connection that drops the instant it opens. Connection failures surface as a typed ConnectError from the connect() / reconnect() result, or as a Disconnected state carrying a DisconnectCause — pattern-match those rather than guessing. This page maps each symptom to its cause and fix.

Kotlin leads the examples and is the source of truth; iOS exposes the same ConnectError / GlassesState types.

Quick checklist (verify these first)

  1. Glasses are powered, charged, and in range. A dead or out-of-range device surfaces as ConnectError.NoDeviceAvailable. Confirm the glasses are paired in the Meta AI app first — Extentos connects to an already-bonded device, it doesn't replace Meta's own pairing.
  2. Bluetooth permissions are granted at runtime. Missing BLUETOOTH_CONNECT / BLUETOOTH_SCAN surfaces as ConnectError.PermissionDenied. The SDK requests BLUETOOTH_CONNECT at runtime, but your app must not have permanently denied it.
  3. A foreground Activity is reachable. Meta registration (the pairing handoff) needs a live Activity — confirm your activityProvider closure returns the current top Activity, not null. See Android lifecycle § Activity wiring.
  4. The Meta DAT auth callback URL scheme is declared. The DAT auth round-trip returns through a custom URL scheme, not a universal/app link. If it's missing or misspelled, the callback never fires and connection hangs (see below).
  5. Run validateIntegration. It catches the structural causes — missing Bluetooth permissions, an unwired bootstrap, an absent DAT configuration — before you ever hit the runtime failure.
  6. Read the event log. getEventLog(filter: 'lifecycle') shows the connection state walk (RegisteredDeviceDiscoveredConnectingActive) so you can see exactly where it stalls; getEventLog(filter: 'errors') surfaces the typed failure.

Pairing dialog never appears

The Meta registration / pairing UI is launched against a foreground Activity. If connect() resolves immediately to ConnectError.RegistrationRequired or nothing visibly happens:

  • Your activityProvider: () -> Activity? returned null — the SDK had no Activity to launch registration from. Wire it to an ActivityLifecycleCallbacks-tracked reference to the current top Activity. See Android lifecycle.
  • The install hasn't registered yet. There is no registration API for you to call — the SDK drives Meta's registration handoff itself, from inside connect() (and therefore inside assistant.start(...)), using your activityProvider to present the companion-app consent screen. So RegistrationRequired almost always means the handoff couldn't run rather than that you forgot to start it: check that activityProvider returns a live Activity, that the glasses are awake and connected in the Meta AI app, and that your package name + signing SHA-256 are registered with Meta. The packaged ExtentosConnectionPage supplies the Activity for you; an app without one supplies it through activityProvider.
  • You aren't enrolled in your own release channel. Meta only lets an account register your integration if it's a member of a channel you've assigned a version to — and that includes the account on your own test glasses. Correct App ID, correct signing SHA, and a still-failing registration usually means this. Check it before chasing activityProvider. Needs firmware v125+; see release channels.
  • You're on the browser simulator, where there is no Bluetooth pairing at all — the surrogate runs in a browser tab. A missing pairing dialog in sim is expected; you attach via the session URL or auto-bind, not a pairing prompt.

Pairing succeeds but the session won't start

The connection state reaches Connecting (or DeviceDiscovered) and stalls, never flipping to Active:

  • ConnectError.PairingFailed — the handshake with the device failed. Power-cycle the glasses, confirm they're bonded in the Meta AI app, and retry. This is usually a transient DAT handshake failure.
  • TransportError.HardwareUnavailable (carried inside DisconnectCause.TransportFailure) — the transport could not reach the hardware. On real glasses this is a Bluetooth/DAT-layer problem; in the simulator it means the browser surrogate denied webcam/mic permission or closed its tab.
  • A SchemaMismatch transport error means the SDK and backend protocol versions diverged — update to a matching SDK build.

Sim ≠ hardware here. A session that starts cleanly in the browser simulator does not guarantee real-hardware pairing succeeds — the simulator swaps the transport for a WebSocket and never exercises Bluetooth bonding or the DAT handshake. Treat real-hardware connection as its own verification pass.

DAT auth callback never fires

Meta DAT completes its auth/registration round-trip by redirecting back into your app through a custom URL scheme (DAT expects a custom scheme, not a universal link). When it's misconfigured, the system browser/Meta app opens, the user authorizes, and control never returns — the connection sits forever in Registered/Connecting.

  • iOS: confirm CFBundleURLTypes declares your custom scheme and LSApplicationQueriesSchemes includes fb-viewapp, alongside the MWDAT dict. generateConnectionModule(platform: "ios") emits the full set — re-run it if you hand-edited Info.plist and the callback stopped working.
  • Android: confirm the callback intent-filter scheme matches what you configured at DAT setup time, and that no other app claims the same scheme.
  • The scheme registered in Meta Developer Center must match the one in your app exactly — a mismatch silently drops the callback.

Glasses connect but disconnect immediately

The state reaches Active and then drops straight back to Disconnected. Branch on the DisconnectCause:

  • DeviceDroppedConnection — Bluetooth fell over right after connecting (interference, the glasses going back to sleep, range). Retryable; reconnect with backoff. See handle disconnects.
  • A fold or overheat — surfaces today as DeviceDroppedConnection (above); the dedicated ThermalCritical / HingesClosed disconnect causes are declared but not yet produced. Wait for the condition to clear, then reconnect.
  • TransportFailure — inspect the carried TransportError (WebsocketClosed, Timeout, HardwareUnavailable) for specifics.

If a connection drops mid-operation, the in-flight call also returns its own typed error (e.g. CaptureError.NotConnected) — handle both the state observer and the per-call result, as covered in handle disconnects.