Skip to main content

onError

Optional callback prop on <BTProvider>. Fires whenever the underlying BLE stack or the SDK's characteristic parser encounters a failure that should be surfaced to your app.

Signature

import type { BleError } from "react-native-ble-plx";
import type { DeviceData } from "@ovok/native";

export interface ErrorCallback {
deviceData?: DeviceData;
error: BleError | Error | string;
}

onError?: (data: ErrorCallback) => void;

deviceData is undefined for errors raised before a device is identified (e.g. the BLE adapter is off, the OS revoked permission mid-scan). Once a known device is matched, subsequent errors carry the DeviceData of the device they relate to.

When it fires

TriggerdeviceDataerror shape
BLE adapter powered offundefinedBleError with errorCode: BluetoothLE
Permission revoked mid-scanundefinedBleError, message includes "permission"
Scan throttling by OSundefinedBleError, message includes "scan"
Device disconnected unexpectedly during a measurementthe device that droppedBleError, message includes "disconnect"
Characteristic parser failed to decode a framethe device that emitted itError with a parser-specific message
Pairing failurethe device that failed to pairBleError
App-level violation (e.g. invalid measurement type for device)the devicestring

The union of BleError | Error | string means you cannot assume .message exists. Always narrow:

function asMessage(e: BleError | Error | string): string {
return typeof e === "string" ? e : e.message;
}

Usage

import React, { useCallback } from "react";
import { Alert } from "react-native";
import { BTProvider } from "@ovok/native";

function MyApp() {
const handleError = useCallback((data) => {
const message = typeof data.error === "string" ? data.error : data.error.message;

if (message.toLowerCase().includes("permission")) {
Alert.alert(
"Bluetooth Permission Needed",
"Please grant Bluetooth and Location permissions in Settings.",
);
return;
}

if (message.toLowerCase().includes("disconnect")) {
// Transient — let the user retry. The SDK will re-scan automatically.
console.warn(
`Device ${data.deviceData?.name ?? "unknown"} disconnected:`,
message,
);
return;
}

// Anything else — surface it.
Alert.alert("Bluetooth Error", message);
}, []);

return (
<BTProvider /* ...other props */ onError={handleError}>
<YourScreens />
</BTProvider>
);
}

Don't confuse with DeviceStatus.Error

There is no DeviceStatus.Error value — the DeviceStatus enum has only 4 values. "Error" is purely a UI label your app derives from onError firing. If you want the rest of your code to treat errors as a status, mirror them into your own state machine:

const [uiStatus, setUiStatus] = useState<UILabel>("idle");

const handleError = useCallback((data) => {
setUiStatus("error");
}, []);

const handleDeviceStatusChanged = useCallback((data) => {
// Map the 4 SDK values to your richer UI labels here.
}, []);

Recovery

There is no automatic retry. After onError fires:

  • Permission failures → drive permissionFallback UI via onAccessPermissionChanged.
  • Transient disconnects → no action; the provider keeps scanning, and the next advertisement re-fires onDeviceFound.
  • Parser failures → safe to ignore one frame; if they repeat, the device firmware may have a different revision than the SDK expects (file an issue with the device model + firmware version).