Skip to content

Bug: hardwareErrorCallback is not passed to HciAdapter, causing an uncaught TypeError on BLE hardware errors #23

@Abasz

Description

@Abasz

When the BLE controller emits a Hardware Error HCI event, the process crashes with:

Apr 29 18:44:52 roeimachine npm[615]: Uncaught Exception: TypeError: hardwareErrorCallback is not a function
Apr 29 18:44:52 roeimachine npm[615]:     at handleHardwareError (/opt/openrowingmonitor/node_modules/ble-host/lib/internal/adapter.js:844:3)
Apr 29 18:44:52 roeimachine npm[615]:     at HciSocket.onData (/opt/openrowingmonitor/node_modules/ble-host/lib/internal/adapter.js:1182:31)
Apr 29 18:44:52 roeimachine npm[615]:     at HciSocket.emit (node:events:519:28)
Apr 29 18:44:52 roeimachine npm[615]:     at /opt/openrowingmonitor/node_modules/hci-socket/lib/hci-socket.js:105:9
Apr 29 18:44:52 roeimachine npm[685]: 2026-04-29 18:44:52 sigHandler: Unhandled signal 15, terminating
Apr 29 18:44:52 roeimachine npm[615]: OpenRowingMonitor shutdown at 18:44, at 2543.14435 seconds,distance 9172.7m
Apr 29 18:44:52 roeimachine npm[615]: /opt/openrowingmonitor/node_modules/ble-host/lib/internal/adapter.js:844
Apr 29 18:44:52 roeimachine npm[615]:                 hardwareErrorCallback(hardwareCode);
Apr 29 18:44:52 roeimachine npm[615]:                 ^
Apr 29 18:44:52 roeimachine npm[615]: TypeError: hardwareErrorCallback is not a function
Apr 29 18:44:52 roeimachine npm[615]:     at handleHardwareError (/opt/openrowingmonitor/node_modules/ble-host/lib/internal/adapter.js:844:3)
Apr 29 18:44:52 roeimachine npm[615]:     at HciSocket.onData (/opt/openrowingmonitor/node_modules/ble-host/lib/internal/adapter.js:1182:31)
Apr 29 18:44:52 roeimachine npm[615]:     at HciSocket.emit (node:events:519:28)
Apr 29 18:44:52 roeimachine npm[615]:     at /opt/openrowingmonitor/node_modules/hci-socket/lib/hci-socket.js:105:9

I beleive the root cause is a missing parameter in the module export at the bottom of lib/internal/adapter.js. The hardwareErrorCallback argument is accepted by HciAdapter internally but is never forwarded from the exported factory function:

// Current code - hardwareErrorCallback is silently dropped:
module.exports = function(transport) {
    return new HciAdapter(transport);
};

// Should be:
module.exports = function(transport, hardwareErrorCallback) {
    return new HciAdapter(transport, hardwareErrorCallback);
};

As a result, hardwareErrorCallback is always undefined inside HciAdapter. When handleHardwareError is triggered by the controller, it calls hardwareErrorCallback(hardwareCode) which throws TypeError: hardwareErrorCallback is not a function, crashing the Node.js process.

Impact

Any BLE hardware error event from the controller — which can occur due to firmware issues, signal interference, or transient hardware faults — will unconditionally crash the entire Node.js application. The error recovery logic inside ble-manager.js (the onHardwareError handler passed via Adapter(transport, onHardwareError)) is completely bypassed and never executes.

Steps to Reproduce

  1. Use BleManager.create() to initialise a BLE manager
  2. Trigger a Hardware Error HCI event from the controller (HCI event code 0x10), for example by inducing a firmware fault or observing it naturally on hardware prone to occasional hardware error events (e.g. Raspberry Pi built-in Bluetooth)
  3. Observe the process crash with TypeError: hardwareErrorCallback is not a function

Fix

One-line change in lib/internal/adapter.js:

module.exports = function(transport, hardwareErrorCallback) {
    return new HciAdapter(transport, hardwareErrorCallback);
};

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