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

# Handle errors from the Trustware SDK

> Catch and respond to errors using the onError callback or try/catch. Use TrustwareErrorCode to identify error types and act on them precisely.

The Trustware SDK surfaces errors through a typed `TrustwareError` class, so you always know what went wrong and why. You can handle errors reactively via the `onError` callback, imperatively by catching thrown errors in the headless core, or by listening for the `error` event in the [lifecycle events](/events-errors/lifecycle-events) stream.

## The `TrustwareError` class

`TrustwareError` extends the native `Error` class with three additional fields:

| Field         | Type                   | Description                                               |
| ------------- | ---------------------- | --------------------------------------------------------- |
| `code`        | `TrustwareErrorCode`   | Machine-readable error code; use this for branching logic |
| `message`     | `string`               | Technical description of the error                        |
| `userMessage` | `string \| undefined`  | Optional human-readable message suitable for display      |
| `cause`       | `unknown \| undefined` | The original error that triggered this one, if any        |

Import it directly from the SDK:

```ts theme={null}
import { TrustwareError } from "@trustware/sdk";
```

## Error codes

The `TrustwareErrorCode` enum covers all error conditions the SDK can produce.

| Code                   | Typical cause                                                               |
| ---------------------- | --------------------------------------------------------------------------- |
| `INVALID_CONFIG`       | The configuration object is missing required fields or has an invalid value |
| `INVALID_API_KEY`      | The API key was rejected; thrown during `Trustware.init()`                  |
| `WALLET_NOT_CONNECTED` | A wallet operation was attempted before a wallet was connected              |
| `BRIDGE_FAILED`        | The cross-chain bridge transaction could not be completed                   |
| `NETWORK_ERROR`        | A network request failed (timeout, DNS failure, or server error)            |
| `INPUT_ERROR`          | The input to a core method (amount, address, etc.) is invalid               |
| `UNKNOWN_ERROR`        | An unexpected error with no more specific classification                    |

<Warning>
  `INVALID_API_KEY` is thrown synchronously during initialization. Make sure to handle it at startup rather than only in your per-transaction error handler.
</Warning>

## Handling errors via `onError`

Pass an `onError` callback in your `TrustwareConfigOptions` to receive all errors emitted by the widget and provider. This is the simplest approach for most integrations.

```ts theme={null}
import { TrustwareProvider, type TrustwareConfigOptions } from "@trustware/sdk";

const config = {
  apiKey: process.env.NEXT_PUBLIC_TRUSTWARE_API_KEY!,
  routes: {
    toChain: "8453",
    toToken: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
  },
  onError: (error) => {
    console.error(error.code, error.message);
  },
} satisfies TrustwareConfigOptions;
```

If you want to display a user-friendly message instead of a raw technical error, use `error.userMessage` when it is defined:

```ts theme={null}
onError: (error) => {
  const display = error.userMessage ?? "Something went wrong. Please try again.";
  showErrorBanner(display);
},
```

<Tip>
  In production, log `error.code` and `error.message` to your error tracking service and display `error.userMessage` to users. This gives you diagnostic detail without exposing internal error strings.
</Tip>

## Handling errors with try/catch

When using the headless core API, errors are thrown as exceptions. Wrap core calls in a `try/catch` block.

```ts theme={null}
import { Trustware, TrustwareError, TrustwareErrorCode } from "@trustware/sdk";

try {
  const route = await Trustware.buildRoute({
    fromChain: "1",
    toChain: "8453",
    fromToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
    toToken: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
    fromAmount: "1000000",
    fromAddress: await Trustware.getAddress(),
    toAddress: "0xDestination...",
  });
} catch (error) {
  if (error instanceof TrustwareError) {
    if (error.code === TrustwareErrorCode.WALLET_NOT_CONNECTED) {
      promptWalletConnection();
    } else {
      console.error(error.code, error.message);
    }
  }
}
```

## The `RateLimitError` class

When your integration hits the API rate limit, the SDK surfaces the 429 as a `RateLimitError`. It extends the native `Error` class directly (not `TrustwareError`), so a single `instanceof TrustwareError` check will not match it; handle it as a separate case.

```ts theme={null}
import { RateLimitError, Trustware } from "@trustware/sdk";

try {
  await Trustware.runTopUp({ fromAmount: "1000000" });
} catch (error) {
  if (error instanceof RateLimitError) {
    // Rate limited; decide how your app should respond.
  }
}
```

The `rateLimitInfo` property has the following shape:

| Field        | Type                  | Description                                                    |
| ------------ | --------------------- | -------------------------------------------------------------- |
| `limit`      | `number`              | Maximum requests allowed in the current window                 |
| `remaining`  | `number`              | Requests remaining in the current window                       |
| `reset`      | `number`              | Unix timestamp when the rate limit window resets               |
| `retryAfter` | `number \| undefined` | Seconds until the limit resets (only present on 429 responses) |
