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

# Errors

> The error envelope and every error code.

```bash theme={null}
BASE_URL="https://api.lucidblock.xyz"
```

## The error envelope

Every error has the same shape. `code` is stable (codes never change meaning or get renamed); `message` is for humans
and may change; `details` is optional and route-specific. Every response, error or not, carries an `X-Request-Id`
header, and the envelope repeats it as `request_id`: quote it when you contact `<CONTACT_EMAIL>`.

> [accordion] Captured example
>
> `GET /v1/solana/wallets/not-a-wallet/defi-positions` → `400` (captured 2026-11-12 from local `error-invalid-address`)
>
> ```json theme={null}
> {
>   "error": {
>     "code": "INVALID_ADDRESS",
>     "message": "wallet must be a base58 32-byte Solana public key",
>     "details": {
>       "param": "wallet"
>     }
>   },
>   "request_id": "25b28921-5f86-4448-8d7c-8798a42b0a00"
> }
> ```

## Codes

| HTTP | `error.code` | When | Retry? | `details` |
| - | - | - | - | - |
| 400 | `INVALID_PARAMETER` | A query parameter is unknown (parameters are strict), out of range or malformed; `include_rewards_in_total=true` without `rewards` in `include`; a malformed cursor | No: fix the request | `param`, `issues` |
| 400 | `INVALID_ADDRESS` | The wallet or program id is not a base58 32-byte key | No | `param` |
| 400 | `UNSUPPORTED_PROTOCOL` | `protocols` names an id not in the registry | No | `param: "protocols"` |
| 400 | `CURSOR_EXPIRED` | The cursor's snapshot has been pruned or is too old to serve | No: restart from the first page | — |
| 401 | `UNAUTHORIZED` | Missing or wrong access token during the private alpha | No: fix the token | — |
| 403 | `FORBIDDEN` | Admin capability token not allowed for the route (internal routes only) | No | — |
| 404 | `NOT_FOUND` | Unknown route or unknown program | No | — |
| 404 | `JOB_NOT_FOUND` | Job id unknown, or the job belongs to another wallet | No: request the wallet again | — |
| 405 | `METHOD_NOT_ALLOWED` | Anything other than GET, HEAD or OPTIONS on `/v1/*` | No | — |
| 409 | `CONFLICT` | Admin state transition not allowed (internal routes only) | No | — |
| 429 | `RATE_LIMITED` | Per-IP rate limit spent, or too many new scans this hour | Yes, after `Retry-After` | `limit`, `retry_after_s`, `reason` (`per_ip_rate` or `cold_scan_limit`) |
| 500 | `INTERNAL` | Unexpected error | Yes, with backoff | — |
| 503 | `DB_UNAVAILABLE` | The database query failed | Yes, with backoff | — |
| 503 | `QUEUE_UNAVAILABLE` | No snapshot, and a scan job could not be created (queue full) | Yes, after `Retry-After` (60 s) | — |
| 503 | `SNAPSHOT_UNAVAILABLE` | No snapshot, and the scan job ended without one (for example `expired`) | Yes, after `Retry-After` | `job_id` |
| 503 | `SCAN_FAILED` | No snapshot, and the scan job failed after its retries | Yes, after `Retry-After` | `job_id`, `job_status` |
| 410 | `ASSET_REMOVED` | A logo file under `/assets/v1/` was removed at the request of its owner | No; use the placeholder or initials | — |
| 503 | `RPC_BUDGET_EXHAUSTED` | No snapshot, and the monthly RPC budget guard blocks new scans | Yes, after `Retry-After` (3,600 s) | — |
| 503 | `CONFIG_INVALID` | A misconfigured production deployment refuses `/v1/*` (except health) | Yes, later | — |

## Troubleshooting by code

* **`INVALID_PARAMETER`**: check the parameter name (unknown names are rejected), ranges (`freshness_seconds`
  0…86,400, `limit` 1…500) and the rewards rule: `include_rewards_in_total=true` needs `rewards` in `include`.

> [accordion] Captured example
>
> `GET /v1/solana/wallets/G4VmLamEV6h15gndx7nHn8TTcu7fJkBBNVN3wTugMNtH/defi-positions?freshness_seconds=-1` → `400` (captured 2026-11-12 from local `error-invalid-parameter`)
>
> ```json theme={null}
> {
>   "error": {
>     "code": "INVALID_PARAMETER",
>     "message": "freshness_seconds: must be an integer",
>     "details": {
>       "param": "freshness_seconds"
>     }
>   },
>   "request_id": "046258a4-d4b8-44e4-a997-4c50a5622b2e"
> }
> ```

* **`INVALID_ADDRESS`**: addresses are case-sensitive base58 and must decode to exactly 32 bytes. Don't lower-case
  them or strip characters.
* **`UNSUPPORTED_PROTOCOL`**: use ids from `/v1/solana/protocols` (for example `native_stake`).

> [accordion] Captured example
>
> `GET /v1/solana/wallets/G4VmLamEV6h15gndx7nHn8TTcu7fJkBBNVN3wTugMNtH/defi-positions?protocols=not_a_protocol` → `400` (captured 2026-11-12 from local `error-unsupported-protocol`)
>
> ```json theme={null}
> {
>   "error": {
>     "code": "UNSUPPORTED_PROTOCOL",
>     "message": "unsupported protocol(s): not_a_protocol; see GET /v1/solana/protocols",
>     "details": {
>       "param": "protocols"
>     }
>   },
>   "request_id": "d52a1d28-1eb1-40fd-82ef-b4696fd8ac45"
> }
> ```

* **`CURSOR_EXPIRED`**: the snapshot behind the cursor is gone or too old to serve; request the first page again.
* **`UNAUTHORIZED`**: send `Authorization: Bearer $LUCIDBLOCK_TOKEN`. Tokens are issued during the alpha at
  `<CONTACT_EMAIL>`.
* **`NOT_FOUND`**: check the path against the [API reference](https://docs.lucidblock.xyz/api-reference/overview.md).
* **`JOB_NOT_FOUND`**: the job is unknown for this wallet (jobs are kept 7 days). Request the wallet again; it returns a
  snapshot or a new job.

> [accordion] Captured example
>
> `GET /v1/solana/wallets/G4VmLamEV6h15gndx7nHn8TTcu7fJkBBNVN3wTugMNtH/defi-positions/jobs/00000000-0000-4000-8000-000000000000` → `404` (captured 2026-11-12 from local `error-job-not-found`)
>
> ```json theme={null}
> {
>   "error": {
>     "code": "JOB_NOT_FOUND",
>     "message": "no such job for this wallet"
>   },
>   "request_id": "438717f5-9ce1-41d5-82f0-a5301d5ce229"
> }
> ```

* **`METHOD_NOT_ALLOWED`**: the API is read-only; use GET.
* **`RATE_LIMITED`**: wait `Retry-After` seconds. `details.reason` is `per_ip_rate` (60 units per minute spent) or
  `cold_scan_limit` (20 new scans per hour from your IP; existing snapshots still load). See
  [Rate limits](https://docs.lucidblock.xyz/reference/rate-limits.md).
* **`INTERNAL`**, **`DB_UNAVAILABLE`**: retry with exponential backoff; if it persists, report the `request_id`.
* **`QUEUE_UNAVAILABLE`**, **`SNAPSHOT_UNAVAILABLE`**, **`SCAN_FAILED`**, **`RPC_BUDGET_EXHAUSTED`**: the wallet has no
  snapshot and none can be produced right now; retry after `Retry-After`.
* **`CONFIG_INVALID`**: a deployment problem on our side; retry later.
* **`FORBIDDEN`**, **`CONFLICT`**: internal admin routes only; public clients never see them.

For retries, partial coverage and null values, see [Error handling](https://docs.lucidblock.xyz/guides/error-handling.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.