# Errors

Errors are returned in the JSON-RPC `error` object. The HTTP status is **200** even for an error — inspect the body, not the status.

```json
{ "jsonrpc": "2.0", "id": 1, "error": { "code": 2001, "message": "not_found", "data": "…" } }
```

`error.data`, when present, carries client-safe detail (a validation reason, a limit). Internal detail is never leaked into it.

## Application codes

| Code | Message | Meaning & remedy |
|---|---|---|
| `1001` | `unauthorized` | Missing or invalid token, bad login, or a throttled login. Re-authenticate. |
| `1002` | `token_expired` | The access token expired. Call [auth.refresh](/docs/methods/auth.refresh) once and retry. |
| `1003` | `forbidden` | Not the owner, or the method is outside a personal access token's scope. |
| `2001` | `not_found` | No such resource owned by the caller. |
| `2002` | `validation_failed` | The request was malformed; `error.data` says why. |
| `3001` | `storage_error` | A transient backend failure while verifying your request (e.g. a database blip). Your token is fine — retry with backoff. |
| `4001` | `custom_crop_limit_exceeded` | The image already has the maximum of five custom crops. |

## JSON-RPC codes

Transport-level errors use the standard JSON-RPC range:

| Code | Meaning |
|---|---|
| `-32700` | Parse error — the body is not valid JSON. |
| `-32600` | Invalid request — not a conforming JSON-RPC object (e.g. a batch on an alias route, or a method that disagrees with the path). |
| `-32601` | Method not found. |
| `-32602` | Invalid params — the params did not match the method's schema. |
| `-32603` | Internal error. |
| `-32605` | The request exceeded the per-method time limit. |

A `batch_too_large` invalid-request (`-32600`) is returned when a batch exceeds 20 requests (see [rate limits](/docs/rate-limits)).
