# Errors

Error codes returned by the Joey browser extension and how to handle them.

Every SDK method rejects with a `JoeyRpcError`:

```ts
class JoeyRpcError extends Error {
  name: 'JoeyRpcError'
  code: number
  message: string
  data?: unknown
}
```

`JoeyRpcError.from(anything)` turns any thrown value into a `JoeyRpcError`. The codes follow EIP-1193 and JSON-RPC.

## Error codes

| `JOEY_ERROR_CODES` | Code | When |
|---|---|---|
| `USER_REJECTED` | 4001 | The user rejected or closed the approval window; the approval expired after 5 minutes; or `connect` was called on a wallet with no accounts. Sites that aren't connected also get 4001 where a locked wallet would otherwise be reported, so lock state isn't revealed. |
| `UNAUTHORIZED` | 4100 | Your site isn't connected; `account` or `tx_signer` isn't one of your granted addresses; the [transaction type isn't permitted](/docs/browser-extension/transactions); your origin can't connect (for example `file:` pages); access was revoked while a request was pending. |
| `UNSUPPORTED_METHOD` | 4200 | Unknown method name. |
| `LOCKED` | 4300 | Joey is locked and the request can't wait for unlock. Rare: most requests wait behind the unlock screen instead. |
| `DISCONNECTED` | 4900 | Joey isn't installed (`requireJoey`, or `waitForJoey` timing out), or the extension can't be reached. |
| `CHAIN_DISCONNECTED` | 4901 | The `chain` you passed doesn't match Joey's network, or the user switched network while the request was pending. |
| `UNRECOGNIZED_CHAIN` | 4902 | Joey reported a chain the SDK doesn't recognise. A `chain` parameter that isn't `xrpl:0`, `xrpl:1` or `xrpl:2` is rejected as `-32602`. |
| `LIMIT_EXCEEDED` | -32005 | Too many requests. Back off; don't retry in a loop. See [rate limits](/docs/browser-extension/permissions#rate-limits). |
| `INVALID_REQUEST` | -32600 | Malformed request. |
| `INVALID_PARAMS` | -32602 | Invalid parameters, including: `tx_json.Account` isn't the signing account; a fee over 2 XRP with `autofill: false`; a `NetworkID` field; an X-address; malformed fields; an invalid `Batch`; oversized params. |
| `INTERNAL` | -32603 | Anything else, including an aborted `waitForJoey`. |

## Handling errors

```ts
import { JOEY_ERROR_CODES, JoeyRpcError, isUserRejection } from '@joeywallet/wallet-sdk'

try {
  await joey.signAndSubmitTransaction({ tx_json })
} catch (error) {
  if (isUserRejection(error)) return // the user said no; not an error to report

  if (error instanceof JoeyRpcError) {
    switch (error.code) {
      case JOEY_ERROR_CODES.UNAUTHORIZED:
        return showError('Not permitted, or not connected.')
      case JOEY_ERROR_CODES.CHAIN_DISCONNECTED:
        return showError('Joey is on a different network.')
      case JOEY_ERROR_CODES.LIMIT_EXCEEDED:
        return showError('Too many requests. Please wait a moment.')
      case JOEY_ERROR_CODES.LOCKED:
        return showError('Unlock Joey and try again.')
    }
  }
  throw error
}
```

Use `isUserRejection(error)` rather than checking `code === 4001`: it also recognises rejections from wallets and shims that only say "reject" in the message.
