---
title: Glasses won't connect
description: 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.
type: troubleshooting
platform: all
vendor: meta
related:
  - /docs/reference/errors
  - /docs/concepts/sessions
  - /docs/troubleshooting
---

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`](/docs/reference/errors#connecterror) from the `connect()` / `reconnect()` result, or as a `Disconnected` state carrying a [`DisconnectCause`](/docs/reference/errors) — 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](/docs/sdk/android/lifecycle).
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 (`Registered` → `DeviceDiscovered` → `Connecting` → `Active`) 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](/docs/sdk/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](/docs/vendors/meta).
- 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](/docs/guides/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](/docs/guides/handle-disconnects#in-flight-operations).

## Related

- [Error reference](/docs/reference/errors) — every `ConnectError`, `CaptureError`, `AudioError`, and `TransportError` payload.
- [Sessions](/docs/concepts/sessions) — the connection-state machine and what reaching `Active` requires.
- [Android manifest setup](/docs/sdk/android/manifest) — the Bluetooth permissions and DAT entries the connection needs.
- [Handle disconnects](/docs/guides/handle-disconnects) — recovering once a connection drops.
- [Troubleshooting](/docs/troubleshooting) — other symptom-shaped fixes.
