Skip to content

[Bug]: BLE connect gives up after the first attempt; the advertised 3 retries only apply to Android error 133 #500

Description

@MrAlders0n

What happens

A user with a T-Deck companion reports having to tap Connect 4 or more times before a session starts. Their debug logs show every failed connect as Connection attempt 1/3 followed immediately by Connection failed. Attempts 2 and 3 almost never run.

One representative stretch from a single Android session:

  1. Three consecutive GATT connect timeouts (fbp-code: 1 | Timed out after 15s), each abandoned after attempt 1 of 3.
  2. Two connections that reached the MeshCore handshake and then died there (writeCharacteristic timeout, then fbp-code: 6 | Device is disconnected), each aborting the whole connection.
  3. Success on the 7th manual tap.

A separate iOS report shows the same shape on auto-reconnect after an app relaunch: one 15s connect timeout on attempt 1 of 3, then give up.

The user's manual re-taps eventually succeed every time, which is exactly the work the internal retry loop was supposed to do.

Why

connect() in lib/services/bluetooth/mobile_bluetooth.dart only treats two error classes as retryable:

  • Android android-code: 133 (GATT_ERROR)
  • iOS bond errors (apple-code 14/15), which are deliberately rethrown without retrying

Everything else is rethrown on the first attempt: the 15s GATT connect timeout, transient GATT errors such as UNKNOWN_GATT_ERROR (28) from setNotifyValue, and service discovery failures. So the advertised 3 attempts only ever apply to error 133.

Separately, failures that happen after the transport connects, during the 9-step protocol handshake (writeCharacteristic timeout, device dropping mid-handshake), abort the connection with no automatic re-run at any level.

Suggested direction

  • Treat connect timeouts and transient GATT errors as retryable inside the existing _maxRetries loop (keeping the iOS bond-error early exit as is).
  • Consider one automatic re-run of the connection workflow when the handshake dies within a few seconds of a successful transport connect.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions