> ## Documentation Index
> Fetch the complete documentation index at: https://bkey.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Error handling

> BmoniSignerError codes and how to handle them.

SDK failures surface as a `BmoniSignerError` — a subclass of `Error` carrying:

* `errorCode` — a numeric `BmoniSignerErrorCode` value for programmatic branching
* `message` — a human-readable description
* `errorCodeHex` — the code formatted the way the native SDKs log it, e.g. `0x30010010`

```ts theme={null}
import { BmoniEmbeddedSdk, BmoniSignerError } from '@bkey-inc/bmoni_embedded_sdk';

try {
  await BmoniEmbeddedSdk.initWallet();
} catch (error) {
  if (error instanceof BmoniSignerError) {
    console.log('Code:', error.errorCodeHex); // 0x30010010
    console.log('Message:', error.message); // "A wallet already exists on this device."
  }
}
```

<Info>
  Use `error instanceof BmoniSignerError` as your discriminator. Failures that are **not** BMONISigner errors — an unavailable native module, a keychain problem — reject with their original React Native error so you can tell them apart.
</Info>

***

## Error codes

### Signing errors (`0x3001xxxx`)

Originate inside the native BMONISigner SDK.

| Constant                | Hex          | When it is thrown                                             |
| ----------------------- | ------------ | ------------------------------------------------------------- |
| `walletAlreadyExists`   | `0x30010010` | `initWallet` called while a wallet is already stored on disk. |
| `signInvalidMessage`    | `0x30010001` | The supplied message could not be processed.                  |
| `signInvalidPrivateKey` | `0x30010002` | The stored key could not be recovered or decrypted.           |
| `signInvalidHash`       | `0x30010003` | The hash argument was not a valid 32-byte hex string.         |
| `signProcess`           | `0x30010004` | Generic ECDSA signing failure.                                |
| `signKeygen`            | `0x30010005` | secp256k1 keypair generation failed.                          |
| `signEip55`             | `0x30010006` | EIP-55 checksum derivation failed.                            |

<Note>
  Storage failures (key creation, encrypt, decrypt) are also passed through
  unmapped, and the native SDK uses a **different range on each platform**:
  **`0x3000xxxx`** on iOS (Secure Enclave) and **`0x3002xxxx`** on Android
  (Keystore). Read `errorCodeHex` rather than matching a single prefix or
  expecting a named constant for them.
</Note>

### PIN errors (`0x4xxxxxxx`)

Generated by the TypeScript-layer PIN gate.

| Constant        | Hex          | When it is thrown                                                               |
| --------------- | ------------ | ------------------------------------------------------------------------------- |
| `pinNotSet`     | `0x40000001` | A PIN-gated call was attempted but no PIN has been set.                         |
| `pinAlreadySet` | `0x40000002` | `setPin` called while a PIN already exists — use `changePin` instead.           |
| `pinMismatch`   | `0x40000003` | The supplied PIN did not match the stored digest.                               |
| `pinInvalid`    | `0x40000004` | The supplied PIN was the wrong length, or omitted while `requirePin` is `true`. |

### Bridge errors (`0x5xxxxxxx`)

Generated by the TypeScript ↔ native bridge.

| Constant                   | Hex          | When it is thrown                                                                                    |
| -------------------------- | ------------ | ---------------------------------------------------------------------------------------------------- |
| `unexpectedNativeNull`     | `0x50000001` | A native method that promised a non-null result did not deliver one — indicates a native-module bug. |
| `walletAddressCacheFailed` | `0x50000002` | A wallet was provisioned, but its address could not be written to secure storage.                    |

***

## Handling the most common cases

```ts theme={null}
import {
  BmoniEmbeddedSdk,
  BmoniSignerError,
  BmoniSignerErrorCode,
} from '@bkey-inc/bmoni_embedded_sdk';

async function handleSigningFlow(userEnteredPin: string) {
  try {
    const sig = await BmoniEmbeddedSdk.signMessage('Hello', userEnteredPin);
    onSuccess(sig);
  } catch (error) {
    if (!(error instanceof BmoniSignerError)) {
      throw error; // platform failure — not an SDK error
    }

    switch (error.errorCode) {
      case BmoniSignerErrorCode.pinNotSet:
        // Redirect the user to the PIN setup flow.
        break;
      case BmoniSignerErrorCode.pinMismatch:
        // Ask the user to re-enter their PIN.
        break;
      case BmoniSignerErrorCode.pinInvalid:
        // PIN was the wrong length or missing.
        break;
      case BmoniSignerErrorCode.walletAlreadyExists:
        // Only thrown by initWallet — show a re-provision dialog.
        break;
      default:
        console.error(`Unexpected SDK error: ${error.message} (${error.errorCodeHex})`);
    }
  }
}
```

***

## Platform errors

If the native module is missing — the app was not rebuilt after installing the package, or the New Architecture is disabled — the module lookup throws as soon as the SDK is imported:

```
Invariant Violation: TurboModuleRegistry.getEnforcing(...):
'BmoniEmbeddedSdk' could not be found.
```

Rebuild the app (`yarn ios` / `yarn android`) rather than reloading the bundle. A Metro reload alone never picks up new native code.
