> For the complete documentation index, see [llms.txt](https://docs.osero.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.osero.com/osero-sdk/reference/error-handling.md).

# Error Handling

## Error Handling

`@osero/client` uses [neverthrow](https://github.com/supermacro/neverthrow) for functional error handling. Every action, preview helper, balance helper, and hosted API method returns a `ResultAsync` — errors are values, not thrown exceptions.

### The ResultAsync pattern

```typescript
const result = await mintUsds(client, request).andThen(sendWith(wallet));

if (result.isErr()) {
  // handle error — result.error is a fully typed union
  console.error(result.error.name, result.error.message);
  return;
}

// success — result.value is TransactionResult
console.log(result.value.txHash);
```

Use `.andThen` to chain operations that return `ResultAsync`. The chain short-circuits on the first error, so you only need to check the final result.

### Error types

All error classes extend `OseroError`, which itself extends the built-in `Error`. `instanceof OseroError` is the broadest catch if you only want to distinguish Osero errors from other exceptions.

#### CancelError

The user rejected the wallet prompt (e.g. clicked "Reject" in MetaMask). With the Privy adapter there is no wallet prompt — `CancelError` corresponds to an aborted Privy API request.

```typescript
case 'CancelError':
  // Show a "Transaction cancelled" message to the user
  break;
```

#### ValidationError

The request contains invalid inputs — for example, `amount` is zero or negative, or (for the hosted API) `slippage` is over the cap or an asset pair is not supported.

```typescript
case 'ValidationError':
  // result.error.message describes what was invalid
  break;
```

#### UnsupportedChainError

The `chainId` in the request is not in `SUPPORTED_CHAIN_IDS`.

```typescript
case 'UnsupportedChainError':
  // Prompt the user to switch to a supported network
  break;
```

#### TransactionError

The transaction was broadcast but reverted on-chain. `.txHash` is always present; `.link` is an optional explorer URL — guard against `undefined` before rendering.

```typescript
case 'TransactionError':
  console.error('Transaction reverted:', result.error.txHash);
  if (result.error.link) {
    console.error('Explorer link:', result.error.link);
  }
  break;
```

#### SigningError

The wallet failed to sign a transaction — for example, the account does not have permission to sign, or the signature was malformed. Privy Wallet API rejections — a wallet policy violation, for example — also surface as `SigningError`.

```typescript
case 'SigningError':
  // result.error.cause has the original error from the wallet
  break;
```

#### UnexpectedError

An unexpected failure — typically an RPC error, a network timeout, or an unhandled condition. Inspect `.cause` for the underlying error.

```typescript
case 'UnexpectedError':
  console.error('Unexpected error:', result.error.cause);
  break;
```

#### ApiRequestError

The hosted API client returned a non-2xx response — e.g. a `401` for an invalid key or a `429` rate limit. `ApiRequestError` is only raised by `OseroApiClient` methods; local actions never produce it.

| Field           | Type             | Description                                            |
| --------------- | ---------------- | ------------------------------------------------------ |
| `statusCode`    | `number`         | HTTP status code returned by the API                   |
| `statusText`    | `string`         | HTTP status text                                       |
| `code`          | `string \| null` | API-supplied error code, when present in the body      |
| `correlationId` | `string \| null` | API-supplied trace ID — quote this in support requests |
| `body`          | `unknown`        | The parsed JSON body, when one was returned            |

```typescript
case 'ApiRequestError':
  console.error('API error', result.error.statusCode, result.error.code);
  if (result.error.correlationId) {
    console.error('Trace ID:', result.error.correlationId);
  }
  break;
```

A network failure (DNS, abort, broken socket) does **not** produce an `ApiRequestError` — it surfaces as `UnexpectedError` with the underlying error on `.cause`.

### Full switch pattern

```typescript
import { mintUsds } from '@osero/client/actions';
import { sendWith } from '@osero/client/viem';

const result = await mintUsds(client, request).andThen(sendWith(wallet));

if (result.isErr()) {
  switch (result.error.name) {
    case 'CancelError':
      showToast('Transaction cancelled.');
      break;
    case 'ValidationError':
      showToast(`Invalid input: ${result.error.message}`);
      break;
    case 'UnsupportedChainError':
      showToast('Please switch to a supported network.');
      break;
    case 'TransactionError':
      showToast(`Transaction failed. View on explorer: ${result.error.link}`);
      break;
    case 'ApiRequestError':
      showToast(`API error (${result.error.statusCode}). Please try again.`);
      console.error('Trace ID:', result.error.correlationId);
      break;
    case 'SigningError':
    case 'UnexpectedError':
      showToast('Something went wrong. Please try again.');
      console.error(result.error.cause);
      break;
  }
  return;
}

showToast(`Success! Transaction: ${result.value.txHash}`);
```

### Inspecting TransactionResult on success

On success, `result.value` is a `TransactionResult`:

```typescript
type TransactionResult = {
  txHash: `0x${string}`;   // Hash of the final transaction
  operations: string[];    // e.g. ['APPROVE_ERC20', 'MINT_USDS']
};
```

`operations` describes what was executed, which is useful for logging or analytics.

For a cross-chain hosted quote, `txHash` is the **source-chain** transaction — the bridge to the destination chain settles asynchronously. Use `getSwapStatusForQuote` to track it; see Actions.

### Catching with instanceof

If you want to handle all Osero errors together without a switch, use `instanceof OseroError`:

```typescript
import { OseroError } from '@osero/client';

try {
  const result = await mintUsds(client, request).andThen(sendWith(wallet));
  if (result.isErr()) throw result.error;
  // ...
} catch (err) {
  if (err instanceof OseroError) {
    console.error('Osero error:', err.name, err.message);
  } else {
    throw err; // re-throw unexpected errors
  }
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.osero.com/osero-sdk/reference/error-handling.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
