# Errors and recovery

Handle structured errors without duplicate writes or hidden spending changes.

Business API errors use a structured envelope:

```json
{
  "error": {
    "code": "QUOTE_EXPIRED",
    "message": "The quote has expired",
    "retryable": false,
    "request_id": "<request identifier>"
  }
}
```

The message above illustrates the shape; actual wording can vary. Use `code` and HTTP status for decisions. Keep `request_id` for support. Do not make behavior depend on parsing an English message.

## Common responses

| Status / code | Next action |
| --- | --- |
| `401 UNAUTHENTICATED` | Check the Bearer key or request a fresh expired registration challenge; do not print the key |
| `403 FORBIDDEN` | Check scope, account ownership, verification, and operation-specific proof |
| `403 ADMISSION_PAUSED` | Paid admissions are paused; stop the paid workflow rather than bypassing it |
| `404 NOT_FOUND` | Check the resource ID and feature availability; inaccessible resources can also appear missing |
| `409 QUOTE_EXPIRED` | Get a fresh quote, re-review it, then reserve if still authorized |
| `409 INSUFFICIENT_FUNDS` | Read spendable balance; fund only with separate authorization or choose a smaller approved task |
| `409 IDEMPOTENCY_CONFLICT` | Inspect the earlier operation and saved request; do not assign a fresh key blindly |
| `409 STALE_VERSION` | Re-read current versions before proposing an updated mutation |
| `422 INVALID_INPUT` | Correct the request schema, ID type, amount string, or compatibility condition |
| `429` | Slow down and respect any returned retry guidance; do not parallelize around the limit |
| `503 UNAVAILABLE` | Back off; inspect the retryable flag and retain mutation identity |

## Recover from timeouts

A network failure does not say whether the server accepted a mutation. Persist the request's idempotency key and body before sending it. For reservation ambiguity, inspect existing rentals and retry the exact supported operation with its original key. For payments, inspect payment and balance state before authorizing a new transfer.

Automatic retries should be bounded, use backoff, and respect `retryable`. Even a retryable error is not authorization to increase a budget, choose a different destination, change assets, or create a second payment.

Quote creation is an explicit exception: repeated quote calls create fresh quotes and do not reserve capacity. Do not apply this behavior to paid reservation requests.

## Report enough, not everything

Include the operation, UTC time, request ID, resource ID, HTTP status, error code, and what you expected. Redact API keys, signatures where sensitive, wallet keys, pairing tokens, and access credentials. See [support](https://docs.amplerun.com/support.md) for the reporting checklist.

---
Last reviewed: 2026-10-19.
Canonical: https://docs.amplerun.com/reference/errors/
