> For the complete documentation index, see [llms.txt](https://docs.augustdigital.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.augustdigital.io/developers/typescript-sdk/errors.md).

# Error Handling

All public SDK methods throw typed errors that extend a common base class, `AugustSDKError`. Catch by class for broad handling, or narrow on the `code` field for actionable, per-failure logic.

## Hierarchy

```
AugustSDKError                   // base — every SDK error extends this
├── AugustAuthError              // missing / invalid / forbidden key
├── AugustValidationError        // caller-side input failed validation
├── AugustNetworkError           // network or transport-level failure
├── AugustTimeoutError           // request exceeded its deadline
├── AugustRateLimitError         // backend returned 429 (or equivalent)
└── AugustServerError            // backend returned a non-OK status
```

Every instance carries:

| Property        | Type                       | Description                                                                |
| --------------- | -------------------------- | -------------------------------------------------------------------------- |
| `code`          | `AugustErrorCode`          | Stable string identifier — narrow on this for per-case handling.           |
| `message`       | `string`                   | Human-readable description suitable for surfacing in dev tools.            |
| `correlationId` | `string \| undefined`      | Set from the response `x-correlation-id` header when the SDK received one. |
| `context`       | `Record<string, unknown>?` | Structured payload (e.g. `{ target, amount }`) attached for logging.       |
| `cause`         | `unknown`                  | Original error from the underlying RPC / fetch — preserved for inspection. |
| `stack`         | `string`                   | Native stack trace.                                                        |

`AugustTimeoutError` adds `timeoutMs` (the deadline that elapsed). `AugustRateLimitError` adds an optional `retryAfterMs`. `AugustServerError` adds `status` (the HTTP status code).

All instances expose `toJSON()` so `JSON.stringify(err)` returns a useful object — native `Error` serializes to `"{}"` without this.

## Codes

| Class                   | Code                 | When it fires                                                                                      | Recommended action                                      |
| ----------------------- | -------------------- | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
| `AugustAuthError`       | `AUTH_MISSING_KEY`   | Required August API key was not supplied to the SDK constructor.                                   | Pass `keys.august` into `new AugustSDK({...})`.         |
| `AugustAuthError`       | `AUTH_INVALID_KEY`   | Backend rejected the supplied key (malformed or revoked).                                          | Verify the key value; rotate if needed.                 |
| `AugustAuthError`       | `AUTH_FORBIDDEN`     | Backend returned HTTP 403 — key lacks permission for this endpoint.                                | Check the key's permitted scopes; do not retry.         |
| `AugustAuthError`       | `AUTH_UNAUTHORIZED`  | Backend returned HTTP 401 — key was not accepted.                                                  | Re-verify the key; do not retry without rotating.       |
| `AugustValidationError` | `INVALID_INPUT`      | Required field missing, `NaN` / `Infinity` amount, or JS number above `Number.MAX_SAFE_INTEGER`.   | Fix the input before retrying.                          |
| `AugustValidationError` | `INVALID_ADDRESS`    | Address fails checksum / wrong length, or is not valid for the target chain family (EVM / Solana). | Fix the input.                                          |
| `AugustValidationError` | `INVALID_CHAIN`      | Chain ID is not in the SDK's allowlist for this operation.                                         | Pass a supported chain.                                 |
| `AugustValidationError` | `INVALID_URL`        | A user-supplied URL failed validation.                                                             | Fix the URL.                                            |
| `AugustValidationError` | `ACCOUNT_NOT_FUNDED` | Stellar (Soroban) deposit/redeem source account has never been activated on-chain (zero balance).  | Send ≥1 XLM to the address to activate it, then retry.  |
| `AugustNetworkError`    | `NETWORK_ERROR`      | Underlying `fetch` / WebSocket failed (DNS, connection refused, offline).                          | Safe to retry with backoff.                             |
| `AugustTimeoutError`    | `TIMEOUT`            | Request exceeded its deadline (default 90 s, configurable per-call).                               | Backoff + retry; check chain / RPC status.              |
| `AugustRateLimitError`  | `RATE_LIMITED`       | Backend returned HTTP 429 (or equivalent rate-limit signal).                                       | Wait `retryAfterMs` before retrying.                    |
| `AugustServerError`     | `SERVER_ERROR`       | Backend returned a non-OK status that is not auth / rate-limit / timeout.                          | Inspect `.status` and `.context`; retry conservatively. |
| `AugustSDKError` (base) | `UNKNOWN`            | Wrapped failure from an RPC / contract call. Original error preserved on `.cause`.                 | Inspect `.cause` and `.context`; do not retry blindly.  |

## Narrowing patterns

### Catch broadly, narrow by code

Best for transactional flows where you want one block of recovery logic per failure category.

```typescript
import {
  AugustAuthError,
  AugustValidationError,
  AugustTimeoutError,
  AugustRateLimitError,
  AugustSDKError,
} from '@augustdigital/sdk';

try {
  await augustSdk.evm.vaultDeposit({
    target: vaultAddress,
    wallet: userAddress,
    amount: '100',
  });
} catch (err) {
  if (err instanceof AugustValidationError) {
    if (err.code === 'INVALID_INPUT') return showFormError(err.message);
    if (err.code === 'INVALID_ADDRESS') return showAddressError();
    if (err.code === 'ACCOUNT_NOT_FUNDED') {
      // Stellar only: the source account needs ≥1 XLM to be activated on-chain.
      // err.message includes the address and the funding hint.
      return showFundingPrompt(err.message);
    }
  }
  if (err instanceof AugustAuthError) {
    return showAuthError('Check your August API key.');
  }
  if (err instanceof AugustTimeoutError) {
    // err.timeoutMs is the deadline that elapsed
    return scheduleRetry(err.timeoutMs);
  }
  if (err instanceof AugustRateLimitError) {
    return scheduleRetry(err.retryAfterMs ?? 5_000);
  }
  if (err instanceof AugustSDKError) {
    // Wrapped downstream failure — inspect cause for the underlying revert / RPC error
    reportError(err.code, err.context, err.cause);
    return;
  }
  throw err;
}
```

### Catch using the type guard

Use `isAugustSDKError` when you receive an `unknown` value (e.g. in a global error handler) and want to keep the rest of the runtime's errors flowing through untouched.

```typescript
import { isAugustSDKError } from '@augustdigital/sdk';

window.addEventListener('unhandledrejection', (event) => {
  if (isAugustSDKError(event.reason)) {
    reportSdkError(event.reason);
    event.preventDefault();
  }
});
```

The guard works across realms (Web Worker, VM contexts) where `instanceof` fails.

### Inspect the original cause

Wrapped errors keep the underlying failure on `.cause`:

```typescript
try {
  await augustSdk.evm.vaultRequestRedeem({ target, wallet, amount });
} catch (err) {
  if (err instanceof AugustSDKError && err.code === 'UNKNOWN') {
    console.error('Underlying error:', err.cause);
    console.error('Context:', err.context);
  }
  throw err;
}
```

For on-chain reverts, `.cause` is the original `ethers` / `viem` error, so revert reasons and gas info remain accessible.

## Retry guidance

| Class                      | Safe to retry?            | Notes                                                               |
| -------------------------- | ------------------------- | ------------------------------------------------------------------- |
| `AugustValidationError`    | No                        | The input is wrong; retrying will fail the same way.                |
| `AugustAuthError`          | No                        | Fix the key first.                                                  |
| `AugustNetworkError`       | Yes, with backoff         | Transient by definition.                                            |
| `AugustTimeoutError`       | Yes, with backoff         | Consider raising `timeoutMs` if the operation is legitimately slow. |
| `AugustRateLimitError`     | Yes, after `retryAfterMs` | Honor the suggested wait.                                           |
| `AugustServerError`        | Conditionally             | Retry on 5xx with backoff; treat 4xx as terminal.                   |
| `AugustSDKError` `UNKNOWN` | Conditionally             | Inspect `.cause` first — an on-chain revert is not retryable.       |

## Serialization for logging

Every SDK error implements `toJSON()`, so logging with `JSON.stringify` preserves the structured fields:

```typescript
try {
  await augustSdk.getVault({ vault });
} catch (err) {
  if (err instanceof AugustSDKError) {
    logger.error('sdk_error', JSON.stringify(err));
  }
  throw err;
}
```

The serialized payload includes `name`, `message`, `code`, `correlationId`, `context`, `stack`, and a compact `cause` summary.
