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

# Error Handling

> Common error scenarios and how to handle them across the Platform API

<Snippet file="product-term-disambiguation.mdx" />

Every Platform API error follows the [RFC 7807 Problem Details](https://tools.ietf.org/html/rfc7807) format. This page covers common error scenarios, retry strategies, and domain-specific error codes.

## Error Format

```json theme={null}
{
  "type": "https://api.sumvin.com/errors/wal-404-001",
  "title": "Wallet Not Found",
  "status": 404,
  "detail": "No wallet found with ID 12345",
  "instance": "/v0/wallets/12345",
  "error_code": "WAL-404-001",
  "trace_id": "abc-123-def"
}
```

| Field        | Description                                                           |
| ------------ | --------------------------------------------------------------------- |
| `type`       | A URI identifying the error type                                      |
| `title`      | A short, human-readable summary                                       |
| `status`     | The HTTP status code                                                  |
| `detail`     | A human-readable explanation specific to this occurrence              |
| `instance`   | The request path that generated the error                             |
| `error_code` | Machine-readable code in `{DOMAIN}-{STATUS}-{SEQUENCE}` format        |
| `trace_id`   | Unique identifier for this request — share with support for debugging |

## Domain Prefixes

Each error code starts with a domain prefix that identifies the resource or subsystem the error originated from. Branch on `error_code` to render domain-specific UI without parsing `detail` strings.

| Prefix  | Domain                                                   |
| ------- | -------------------------------------------------------- |
| `USR`   | Users and accounts                                       |
| `ONB`   | Onboarding state machine                                 |
| `WAL`   | Wallets (EOA and Safe)                                   |
| `KYC`   | KYC verification                                         |
| `SAF`   | Safe smart contract creation                             |
| `SGN`   | Agent signer setup                                       |
| `STS`   | User status transitions                                  |
| `PHONE` | Phone verification                                       |
| `TXN`   | Transactions                                             |
| `RCT`   | Receipts                                                 |
| `BUD`   | Budgets                                                  |
| `INS`   | Insights                                                 |
| `CRD`   | Cards                                                    |
| `CHT`   | Chat sessions and messages                               |
| `IPA`   | Errand (Intelligent Purchase Authorisation) operations   |
| `PINT`  | Stamped Mandate (Purchase Intent) signing and validation |
| `PAY`   | Payment Links and x402 settlement                        |
| `SIS`   | Sumvin Identity Service (org/env/member/keys)            |
| `BNK`   | Bank linking and open banking                            |
| `RMP`   | On/off-ramp sessions                                     |
| `ACC`   | Accounts                                                 |
| `AST`   | Assets                                                   |
| `GEN`   | General validation                                       |
| `SYS`   | Internal system errors                                   |

The tables below cover the most common errors integrators encounter on the Platform API. The full catalogue is reflected in the OpenAPI spec.

## Common HTTP Status Codes

| Status | Meaning           | Action                                                             |
| ------ | ----------------- | ------------------------------------------------------------------ |
| 200    | Success           | —                                                                  |
| 201    | Created           | Resource created successfully                                      |
| 202    | Accepted          | Async operation started — poll `_links` for completion             |
| 208    | Already Reported  | Idempotent replay — resource already exists, returned as-is        |
| 400    | Bad Request       | Fix the request body or parameters                                 |
| 401    | Unauthorized      | Check your JWT or API key                                          |
| 403    | Forbidden         | Valid credentials but insufficient permissions                     |
| 404    | Not Found         | Resource doesn't exist — check the ID                              |
| 409    | Conflict          | Resource state conflict (e.g., duplicate wallet)                   |
| 422    | Unprocessable     | Missing or invalid required fields                                 |
| 424    | Failed Dependency | Upstream dependency not ready (e.g., agent signer not provisioned) |
| 429    | Too Many Requests | Rate limited — wait for `Retry-After` header duration              |
| 500    | Internal Error    | Retry with exponential backoff                                     |

## Authentication Errors

| Error Code    | Status | Description                 | Resolution                                                                             |
| ------------- | ------ | --------------------------- | -------------------------------------------------------------------------------------- |
| `USR-401-001` | 401    | Missing or invalid JWT      | Check `x-juno-jwt` header contains a valid, unexpired token                            |
| `USR-404-001` | 404    | No user exists for this JWT | Create the user first with [`POST /v0/user/`](/api-reference/user/create-user-account) |

## User & Onboarding Errors

| Error Code    | Status | Description                              | Resolution                                                                                                         |
| ------------- | ------ | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `USR-409-001` | 409    | User already exists                      | Use the existing user — [`POST /v0/user/`](/api-reference/user/create-user-account) returns `208 Already Reported` |
| `USR-422-001` | 422    | Missing required fields on user creation | Include `primary_eoa_address` and `chain_id`                                                                       |

## Wallet Errors

| Error Code    | Status | Description                                                                             | Resolution                                                                                                                                             |
| ------------- | ------ | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `WAL-400-001` | 400    | Invalid Ethereum address format                                                         | Provide a valid 0x-prefixed, checksummed address                                                                                                       |
| `WAL-400-002` | 400    | Chain ID does not match primary chain                                                   | Use the same chain as the primary wallet                                                                                                               |
| `WAL-400-004` | 400    | Primary chain is locked because a Safe wallet is already persisted on a different chain | Don't try to switch primary chain after a Safe has been deployed. See [Wallets Guide](/guides/wallets#primary-chain-is-locked-once-a-safe-is-deployed) |
| `WAL-403-001` | 403    | Cannot delete primary wallet                                                            | Set another wallet as primary first                                                                                                                    |
| `WAL-403-002` | 403    | Wallet belongs to another user                                                          | Verify the wallet ID                                                                                                                                   |
| `WAL-403-003` | 403    | Wallet address not in verified credentials                                              | Verify wallet ownership — see [Wallets Guide](/guides/wallets#wallet-ownership-verification)                                                           |
| `WAL-404-001` | 404    | Wallet not found                                                                        | Check the wallet ID; list wallets via [`GET /v0/wallets`](/api-reference/wallets/list-wallets)                                                         |
| `WAL-409-001` | 409    | Wallet already exists for this address and chain                                        | Use the existing wallet                                                                                                                                |
| `USR-424-001` | 424    | No active agent signer                                                                  | Wait for onboarding to complete before setting a primary wallet                                                                                        |

## Onboarding Errors

| Error Code    | Status | Description                                                                                                    | Resolution                                                                                                    |
| ------------- | ------ | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `ONB-409-001` | 409    | Submitted step does not match the user's current step                                                          | Read [`GET /v0/user/me/onboarding/steps`](/api-reference/user/get-onboarding-steps) and submit `current_step` |
| `ONB-409-002` | 409    | The targeted onboarding step is already completed (BYO Safe / user-signed deploy submission for a closed step) | The user is already past this step — fetch their current state and route accordingly                          |

## Safe Operation Errors

| Error Code    | Status | Description                                                                                     | Resolution                                                                           |
| ------------- | ------ | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| `SAF-400-012` | 400    | User-signed Safe deploy verification failed (not a Safe, wrong owners, wrong contract version)  | Permanent — do not retry. The deployed contract does not match expectations.         |
| `SAF-409-001` | 409    | Idempotency-Key reused with a different request body                                            | Use a fresh key for a different request, or replay the original                      |
| `SAF-503-001` | 503    | User-signed Safe deploy finalisation hit a transient error after the UserOperation was included | Pause polling for the `Retry-After` interval (default 5s) then retry the status poll |

## SIS Configuration Errors

| Error Code    | Status | Description                                                                            | Resolution                                                                             |
| ------------- | ------ | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| `SIS-409-008` | 409    | Mutually-exclusive features both requested enabled (`ai_agent` + `user_signed_deploy`) | Disable one before enabling the other. See [Environment features](/dashboard/features) |

## KYC Errors

| Error Code    | Status | Description                     | Resolution                                                                                                                |
| ------------- | ------ | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `KYC-403-001` | 403    | KYC already submitted           | Check status with [`GET /v0/kyc/status`](/api-reference/kyc/get-current-kyc-verification-status) instead of re-submitting |
| `KYC-409-001` | 409    | KYC session already in progress | Wait for the existing session to complete                                                                                 |

## Retry Strategy

### Retryable Errors

These errors are transient and should be retried with exponential backoff:

| Status | Strategy                                                           |
| ------ | ------------------------------------------------------------------ |
| 429    | Wait for the `Retry-After` header value, then retry                |
| 500    | Retry up to 3 times with exponential backoff (1s, 2s, 4s)          |
| 424    | Retry after a delay — the upstream dependency may become available |
| 202    | Not an error — poll the linked resource for completion             |

### Non-Retryable Errors

These indicate a problem with the request itself:

| Status | Action                                                                 |
| ------ | ---------------------------------------------------------------------- |
| 400    | Fix the request body or parameters                                     |
| 401    | Refresh or replace the authentication token                            |
| 403    | Check permissions — the action may not be allowed in the current state |
| 404    | Verify the resource ID exists                                          |
| 409    | Resolve the conflict — typically by using the existing resource        |

### Example: Retry with Backoff

```typescript theme={null}
async function apiCall(url: string, options: RequestInit, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.ok || response.status === 208) return response;

    if (response.status === 429) {
      const retryAfter = parseInt(response.headers.get("Retry-After") ?? "30");
      await new Promise((r) => setTimeout(r, retryAfter * 1000));
      continue;
    }

    if (response.status >= 500 && attempt < maxRetries) {
      await new Promise((r) => setTimeout(r, Math.pow(2, attempt) * 1000));
      continue;
    }

    const error = await response.json();
    throw new ApiError(error.error_code, error.detail, error.trace_id);
  }
}
```

## SIS Error Codes

For error codes from the Sumvin Identity Service (token exchange, revocation), see the [SIS Error Reference](/merchant/errors).
