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

# Errors

> Every error code the Gomry Cloud API returns, what causes it, whether it is retryable, and whether the failed request was billed.

Errors are JSON, with a stable machine-readable `error` code and a human `message`. Branch on the code — the message is written for a person and may be reworded.

<h2 id="shape">
  The shape
</h2>

```json theme={null}
{
  "error": "api_not_enabled",
  "message": "scrape is not enabled for this project. Enable it in the console."
}
```

The `x-request-id` header is present on errors too, including on a `500`. Capture it — without it a report of an intermittent failure cannot be traced back to the request that produced it.

<h2 id="codes">
  Codes
</h2>

| Status | Code                   | Meaning                                                                                                         |
| ------ | ---------------------- | --------------------------------------------------------------------------------------------------------------- |
| 400    | `validation_error`     | The body failed schema validation. `details.issues` names the fields that failed, by path — never their values. |
| 401    | `unauthorized`         | Key missing, malformed, unknown, revoked or expired.                                                            |
| 403    | `forbidden`            | The key is valid but lacks the scope for this operation.                                                        |
| 403    | `api_not_enabled`      | The project has not enabled this API.                                                                           |
| 404    | `not_found`            | The addressed resource does not exist, or is not yours to see.                                                  |
| 409    | `conflict`             | The request conflicts with the current state — a name already taken, for example.                               |
| 402    | `billing_required`     | The organization has no payment method. Add a card.                                                             |
| 402    | `billing_past_due`     | The last invoice could not be collected. Update the card.                                                       |
| 402    | `billing_suspended`    | Billing is suspended. Contact support.                                                                          |
| 402    | `insufficient_credit`  | The project reached its monthly budget cap.                                                                     |
| 429    | `rate_limited`         | Too many requests for this key. Back off and retry.                                                             |
| 502    | `upstream_error`       | A provider we depend on failed.                                                                                 |
| 503    | `provider_unavailable` | The service is not currently configured to serve. Retry.                                                        |
| 500    | `internal_error`       | A fault on our side. Retry, and send us the request id.                                                         |

Individual services add codes of their own for a failure that is specific to them — `scrape_failed` and `fetch_failed` are both `502` and both mean the page could not be retrieved. They are documented on each [service's page](/services).

A `400` carries a `details` object naming what was wrong: `{"error":"validation_error","message":"Invalid request body","details":{"issues":["prompt"]}}` means the `prompt` field failed. Only validation errors carry it, and only field names, allowed values and limits — never the values you sent, and never anything about your organization.

<h2 id="billing-on-failure">
  What a failure costs
</h2>

<Note>
  Only work that produced a result is billed. A validation error, an auth failure, a rate limit, a timeout, or an upstream failure costs nothing.
</Note>

Failed requests are still recorded, so they appear in your usage dashboard with their status — you can see a spike of `429`s without being charged for it. The quantity billed is what the handler actually consumed, which is why a partially successful call (an extraction that needed a retry) reports exactly what it used in the response body.

<h2 id="retrying">
  Retrying
</h2>

* Retry `429`, `500`, `502` and `503` with exponential backoff and jitter.
* Do not retry `400`, `401` or `403` — the same request will fail identically until you change something.
* Do not retry `402` in a loop. It means spending is blocked until a human adds a card, fixes one, or raises a budget.
* Retries are billed like any other request: a successful retry of a failed call is one billable unit, because the failed attempt was free.
