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

# Errors

> The error envelope, its stable codes, and when to retry.

Every error uses one envelope, whether a request is refused or a generation or
one of its outputs fails:

```json theme={null}
{
  "error": {
    "code": "validation_failed",
    "message": "Too big: expected number to be <=4",
    "param": "output.count",
    "retryable": false
  }
}
```

| Field | Description |
| - | - |
| `code` | A stable, machine-readable code in lowercase `snake_case`. Codes are part of the contract: branch on `code`. |
| `message` | A sentence for people. Messages can change, so don't parse them. |
| `param` | Optional. The request field, header, or query parameter at fault, such as `inputs[0].url`, `Idempotency-Key`, or `cursor`. Nested fields use dots, and array items use `[index]`. |
| `retryable` | Whether sending the same request again can succeed. |
| `details` | Optional. An object with more facts about the error. Each code below says which details it carries. |

A failed generation reports the envelope's inner object as its `error`, and
each failed output reports one as its own `error`.

## Retry errors

Retry a request only when `retryable` is `true`. Back off between attempts, and
for a `429`, wait at least the number of seconds in the `Retry-After` header.
Send the same `Idempotency-Key` on each retry of a `POST`, so that a retry never
starts a second generation. For details, see [Idempotency](https://docs.zerogen.com/idempotency.md).

## Request errors

| Status | Code | Meaning |
| - | - | - |
| `400` | `invalid_request` | The request is malformed: the body isn't valid JSON, it has an unknown field, a query parameter is unknown or sent twice, the `Idempotency-Key` header isn't 1 to 255 printable ASCII characters, or an endpoint that takes no body received one. |
| `405` | `invalid_request` | The endpoint doesn't accept this method. The `Allow` header lists the methods it accepts. |
| `413` | `invalid_request` | The request body is larger than 128 KiB. |
| `415` | `invalid_request` | The request body isn't sent as `application/json`. |
| `400` | `validation_failed` | A value is invalid for the endpoint or for the model's request schema, or a `cursor` doesn't match the filters sent with it. |
| `400` | `model_unavailable` | The model isn't available to your organization, or it's past its sunset date. `param` is `model`. |
| `400` | `input_import_failed` | ZeroGen couldn't import a URL input. `param` names the input, such as `inputs[1].url`. Nothing is charged. |
| `401` | `invalid_api_key` | The API key is missing, malformed, unknown, revoked, or expired. |
| `402` | `insufficient_balance` | Your organization's available balance can't cover the generation's quote. `details` carries `availableMicroUsd` and `requiredMicroUsd`. |
| `402` | `spend_limit_reached` | The generation would pass your organization's monthly spend limit or the project's monthly budget. An admin can raise them. |
| `402` | `cost_limit_exceeded` | The quote is higher than the request's `maxCostMicroUsd`. `details` carries `quotedMicroUsd` and `maxCostMicroUsd`. |
| `403` | `permission_denied` | The key lacks the endpoint's scope (`details.scope` names it), the request came from a browser, the API isn't enabled for your organization, a test key reached outside its sandbox, or the owner's membership doesn't allow the action. |
| `404` | `not_found` | No such endpoint, or no resource with this ID that the key can reach. An ID that isn't a UUID is also `not_found`. |
| `409` | `idempotency_conflict` | The `Idempotency-Key` was already used for a different request. |
| `409` | `idempotency_in_progress` | A request with this `Idempotency-Key` is still running. Retryable. |
| `409` | `invalid_state` | The generation needs a person's approval, so an API key can't start it. For example, a generation that runs on your organization's own provider key with no provider list price. `details.approvalReason` says why. |
| `429` | `rate_limited` | A rate limit, a running-generation cap, or a URL import limit was reached. Retryable after `Retry-After`. For details, see [Rate limits](https://docs.zerogen.com/rate-limits.md). |
| `500` | `internal` | Something went wrong in ZeroGen. Retryable. |
| `503` | `pricing_unavailable` | ZeroGen can't price the generation right now. `retryable` says whether a retry can help. |
| `503` | `unavailable` | ZeroGen can't check API keys right now, which is retryable, or your organization's balance isn't available, which isn't. |

### Validation details

A `validation_failed` or `invalid_request` error from schema validation names
the first problem in `message` and `param`. When the request has more than one
problem, `details.issues` lists up to 10 of them, each with a `message` and,
when it applies, a `param`:

```json theme={null}
{
  "error": {
    "code": "validation_failed",
    "message": "Too big: expected number to be <=4",
    "param": "output.count",
    "retryable": false,
    "details": {
      "issues": [
        { "param": "output.count", "message": "Too big: expected number to be <=4" },
        { "param": "output.durationSeconds", "message": "Too small: expected number to be >0" }
      ]
    }
  }
}
```

## Generation and output errors

A generation's `error` and each output's `error` use one of the following
codes.

| Code | Meaning |
| - | - |
| `provider_error` | The model provider failed, or returned fewer outputs than requested. |
| `provider_timeout` | The provider didn't finish in time. |
| `content_moderation` | The provider refused the request under its content policy. |
| `input_rejected` | The provider couldn't use an input, for example because it couldn't read the file. |
| `internal` | Something went wrong in ZeroGen. |

`retryable` says whether creating the same generation again can succeed.
`details.reason` gives a more specific cause, and `details.providerMessage`
sometimes carries the provider's own message. Both are for diagnosis: their
values can change, so don't branch on them.

A failed output isn't charged for its output, but a generation is still charged
for billable work that actually happened. For details, see [Billing](https://docs.zerogen.com/billing.md).


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