Skip to content

nordic: report GATT write errors and map more ATT errors - #11553

Open
dhalbert wants to merge 3 commits into
adafruit:mainfrom
dhalbert:nordic-gatt-att-errors
Open

dhalbert wants to merge 3 commits into
adafruit:mainfrom
dhalbert:nordic-gatt-att-errors

Conversation

@dhalbert

Copy link
Copy Markdown
Collaborator

Diagnosis and code by Claude, reviewed by @dhalbert.

Error reporting

ATT error Exception
0x02 Read Not Permitted BluetoothError: read not permitted
0x03 Write Not Permitted BluetoothError: write not permitted
0x05 Insufficient Authentication SecurityError: Insufficient authentication
0x08 Insufficient Authorization SecurityError: Insufficient authorization
0x0C Insufficient Encryption Key Size, 0x0F Insufficient Encryption SecurityError: Insufficient encryption
0x0D Invalid Attribute Value Length ValueError: Invalid length
any other BluetoothError: Unknown gatt error: 0x01xx
  • Statuses that are not ATT errors, such as BLE_GATT_STATUS_UNKNOWN, raise "Unknown BLE error: 0x%04x".

Bug fixes

  • bleio_gattc_write() did not wait for the response to a write request, so errors from the peer were never reported, and a rejected write appeared to succeed.
    • It now waits for BLE_GATTC_EVT_WRITE_RSP or a disconnect and checks the status. Writes without response are unchanged.
  • If the connection dropped during bleio_gattc_read(), its event handler stayed registered with a pointer to a dead stack frame, and wrote through it on the next disconnect event.
    • It now removes the handler before anything can raise.

Testing

Feather nRF52840 with this PR, Metro ESP32-S3 on espressif main plus #11552:

Test Result
Metro central, Feather peripheral: read/write NO_ACCESS, unpaired read of ENCRYPT_NO_MITM, over-length write to fixed_length read not permitted, write not permitted, Insufficient authentication, Invalid length
Feather central, Metro peripheral: unpaired read of ENCRYPT_NO_MITM, over-length write to fixed_length Insufficient authentication, Invalid length
ble_uart_echo_test.py / ble_uart_echo_client.py from the BLE library examples, both directions echoes received, no errors
Disconnect during a read/write loop, then reconnect and disconnect again ConnectionError, then no problems

dhalbert and others added 3 commits October 11, 2026 12:50
`check_gatt_status()` now maps the same ATT errors as espressif:

- 0x02, 0x03: `BluetoothError("read not permitted")` / `"write not permitted"`
- 0x08: `SecurityError("Insufficient authorization")`
- 0x0C: `SecurityError("Insufficient encryption")`, like 0x0F
- 0x0D: `ValueError("Invalid length")`

Other ATT errors still report "Unknown gatt error: 0x01xx". Statuses
outside the ATT range, such as `BLE_GATT_STATUS_UNKNOWN`, now report
"Unknown BLE error" instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`bleio_gattc_write()` sent a write request and returned without waiting
for the response, so an error from the peer was never seen and the write
appeared to succeed. It now waits for `BLE_GATTC_EVT_WRITE_RSP` (or a
disconnect) and passes the status to `check_gatt_status()`, as
`bleio_gattc_read()` does. Writes without response are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
If the connection dropped during `bleio_gattc_read()`, the
`bleio_check_connected()` check raised before the event handler was
removed. The handler stayed registered with a pointer to the dead
stack frame, and wrote through it on the next disconnect event. Remove
the handler first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant