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

# Errors

> Error shape and every code the API returns.

Errors return a JSON body with a human-readable `error` and a stable machine-readable `code`.

```json theme={null}
{
  "error": "Invalid wallet address format. Expected 0x followed by 40 hex characters.",
  "code": "INVALID_ADDRESS"
}
```

Branch on `code`. The `error` string is written for humans and may be reworded.

## Codes

| Code                  | Status | Cause                                                                                            |
| --------------------- | ------ | ------------------------------------------------------------------------------------------------ |
| `MISSING_API_KEY`     | 401    | No `Authorization` header.                                                                       |
| `INVALID_API_KEY`     | 401    | Key is unrecognized, revoked, or expired.                                                        |
| `RATE_LIMIT_EXCEEDED` | 429    | A per-minute, per-day or per-month limit was hit. See [rate limits](/api-reference/rate-limits). |
| `INVALID_ADDRESS`     | 400    | An address is not `0x` plus 40 hex characters.                                                   |
| `INVALID_HANDLE`      | 400    | X handle is not 1 to 15 characters of letters, numbers or underscores.                           |
| `INVALID_USERNAME`    | 400    | Farcaster username is not 1 to 20 characters of lowercase letters, numbers or underscores.       |
| `INVALID_PARAMETER`   | 400    | A query parameter is out of range, such as an unrecognized `period`.                             |
| `INVALID_REQUEST`     | 400    | Body is missing, not valid JSON, or `wallets` is absent or empty.                                |
| `INVALID_REQUEST`     | 413    | Request body exceeded 1 MB.                                                                      |
| `BATCH_SIZE_EXCEEDED` | 400    | More wallets than your plan’s batch limit.                                                       |
| `SERVICE_UNAVAILABLE` | 503    | Datastore is temporarily unreachable. Retry with backoff.                                        |
| `INTERNAL_ERROR`      | 500    | Unexpected failure on our side.                                                                  |

## Things that are not errors

Two cases return HTTP 200 and are easy to mistake for failures.

**A wallet with no identities.** `data: null`, `meta.found: false`. The lookup succeeded and the answer is that there is nothing attached. See [found, missing, and checked](/concepts/data-quality#found-missing-and-checked).

**A reverse lookup with no matches.** `data: []`, `meta.total_count: 0`.

## Retrying

`SERVICE_UNAVAILABLE` and `INTERNAL_ERROR` are worth retrying with exponential backoff. `RATE_LIMIT_EXCEEDED` is worth retrying once the window resets.

Nothing in the `400` family is worth retrying. The request is malformed and will fail identically until you change it. `BATCH_SIZE_EXCEEDED` is the exception in spirit: split the batch and retry the pieces.

`401` means the key is wrong. Retrying will not fix it and repeated failures are a good way to look like an attack.
