Skip to content

Bug: ATT_FIND_INFORMATION_RESPONSE exceeds MTU on small MTU connections (e.g., Garmin watches) #20

@Abasz

Description

@Abasz

I think there is a calculation error in the GATT server implementation that causes the ATT_FIND_INFORMATION_RESPONSE to exceed the negotiated MTU. This occurs because the code calculates the maximum number of attributes that can fit in a packet based only on the UUID size, forgetting to account for the 2-byte Attribute Handle that precedes each UUID in the response list.

This results in a protocol violation. While clients with large MTUs (like Android/iOS) may not notice (because they renegotiate MTU on connection before doing anything else), clients with the default BLE MTU of 23 bytes (like Garmin watches) will receive a packet larger than 23 bytes and immediately drop the connection.

The Bug in lib/internal/gatt.js:

var max16 = (currentMtu - 2) / 2 >>> 0;

In the handler for ATT_FIND_INFORMATION_REQUEST, the limits are currently calculated as:

var max16 = (currentMtu - 2) / 2 >>> 0;
var max128 = (currentMtu - 2) / 16 >>> 0;

Why this is incorrect:
The ATT_FIND_INFORMATION_RESPONSE format consists of:

  • 1 byte: Opcode
  • 1 byte: Format
  • N bytes: Information Data List (where each entry is 2 bytes Handle + UUID)

For a 16-bit UUID format, each entry is 4 bytes, not 2.
For a 128-bit UUID format, each entry is 18 bytes, not 16.

Example Failure Case:
On a connection with currentMtu = 23:

  1. The code calculates max16 as (23 - 2) / 2 = 10.
  2. It attempts to pack 10 entries into the response.
  3. The resulting packet size is 2 + (10 * 4) = 42 bytes.
  4. The server sends a 42-byte packet over a 23-byte link, causing a disconnect.

Suggested Fix:

Update the divisors to account for the 2-byte handle:

// Each entry is: 2 bytes (Handle) + UUID size (2 or 16)
var max16 = Math.floor((currentMtu - 2) / 4);
var max128 = Math.floor((currentMtu - 2) / 18);

I am happy to create a PR with the fix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions