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 { BluetoothError, BluetoothErrorCode, DeviceData } from "@ovok/native";
export interface ErrorCallback {
deviceData?: DeviceData;
error: BluetoothError | Error | string;
code?: BluetoothErrorCode;
}
onError?: (data: ErrorCallback) => void;
deviceData is undefined for errors raised before a device is identified. Once a
known device is matched, subsequent errors normally carry the related DeviceData.
Use code when present; do not parse a translated message as a machine-readable
identifier.
When it fires
| Trigger | deviceData | error shape |
|---|---|---|
| BLE adapter powered off | undefined or known device | normalized Bluetooth error |
| Permission revoked mid-scan | undefined | bluetooth.permission-denied when classified |
| Scan throttling by OS | undefined | bluetooth.scan-failed when classified |
| Device disconnected during a measurement | the device when known | connection error |
| Parser rejected a frame | the device when known | frame/measurement error |
| Pairing failure | the device when known | bluetooth.pairing-required when classified |
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
Connection setup retries a bounded number of times internally. After onError fires:
- Permission failures → drive
permissionFallbackUI viaonAccessPermissionChanged. - Transient disconnects → the provider keeps scanning; the manager de-duplicates a peripheral while it is already known and will surface it again after the device is removed by the connection lifecycle.
- 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).
Related
- BTProvider — full provider reference
- on-device-status-changed — the canonical 4-value DeviceStatus enum
- on-access-permission-changed — permission-specific error handling