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

# Error contract

> Handle stable, provider-neutral Agent API failures across REST, CLI, and MCP.

# Error contract

This page describes image and sprite errors. [Video errors](/agent-api/video-jobs#common-errors) include quote-specific reasons and synchronous admission rejections. In particular, Video acceptance can return `402 insufficient_credits` and `429 too_many_active_jobs`; the image admission rules below do not apply to those requests.

Branch on `error.reason` and `error.retryable`. Do not match message text. Messages are short, sanitized explanations and may be clarified without changing the stable reason.

HTTP errors use this additive envelope (the example illustrates the general credit error shape; `/v1/execute` reports credit admission failures later in execution state):

```json theme={null}
{
  "error": {
    "code": "BUDGET_EXCEEDED",
    "reason": "insufficient_credits",
    "message": "The account has insufficient credits.",
    "category": "BUDGET",
    "retryable": false,
    "request_id": "018f3ef0-05f4-7c92-a6de-4ad4894f7b63"
  }
}
```

`code` and `category` remain for clients built against the earlier envelope. New integrations should use `reason`. The `X-Request-ID` response header matches `error.request_id`. Error responses send `Cache-Control: no-store`.

## Details

A request that fails because one field is wrong also carries `error.details`, so you can correct the request without guessing:

```json theme={null}
{ "field": "input_asset_id", "issue": "required" }
```

A body that fails schema validation instead carries `error.details.field_errors`, one entry per field. `details` is sanitized and never echoes a submitted value, so read `field` and `issue` rather than matching on text. Not every error has `details`; treat it as optional.

## Stable reasons

For the managed execution flow, distinguish HTTP rejection from asynchronous admission and job failures. A status read returning HTTP `200` can still contain a failed execution.

| Reason | Where it appears | Retryable | Client action |
| - | - | - | - |
| `invalid_request` | HTTP `400`, `405`, `413`, `422` for request validation; failed execution for admission validation | No | Correct the request, headers, or input asset. After a terminal failure, a deliberate new attempt needs its own key. |
| `authentication_failed` | `401` | No | Replace an invalid or revoked API key. A missing Authorization header returns `422 invalid_request`. |
| `access_denied` | HTTP `403` for access checks before acceptance; failed execution for later admission denial | No | Check account access and canonical execution state before deciding on a new attempt. |
| `resource_not_found` | `404` | No | Check the opaque ID and the account that owns it. |
| `insufficient_credits` | Failed execution after acceptance | No | Add credits before deliberately creating a new attempt after terminal failure. |
| `conflict` | `409` | No | Read canonical state. Do not reuse one idempotency key for a different body. |
| `too_many_active_jobs` | Not exposed during managed admission; execution stays queued | Service retries | Keep following the existing execution. Do not resubmit to obtain a slot. |
| `rate_limited` | HTTP `429` for request or stream limits; admission throttling stays queued | Yes | Back off on HTTP rejection; follow accepted work. Replay only an uncertain submission with its original body and key. |
| `quota_exceeded` | Failed execution after acceptance | No | Wait for the documented quota window or ask the account owner to review the limit. |
| `content_refused` | Job failure | No | Change the request. |
| `temporarily_unavailable` | `500`, `502`, `503`, `504`, or job failure | Yes | Back off and inspect canonical state before retrying. |
| `generation_failed` | Job failure | No | Inspect the request ID and contact support if the request should succeed. |
| `prompt_policy_blocked` | `422` | No | Restricted product hosts only. The message names the block category (minors, drug or medication references, listed characters). Adult clothing, underwear and nudity edits on an adult are not blocked here; the image provider's own safety system decides them and a refusal is reported as `content_refused`. |
| `feature_unavailable` | `403` | No | Restricted product hosts only. The capability is not offered on that host; use the primary DreamLayer host. |

## Execution admission

`POST /v1/execute` accepts durable work before checking credits, quota, and active-job admission. A non-retryable admission failure is a failed execution, returned by `GET /v1/executions/{execution_id}` and its `done` event:

```json theme={null}
{"status":"failed","error":{"reason":"insufficient_credits","message":"The account has insufficient credits.","retryable":false}}
```

There is no submit-time `402` for these execution admission failures. Retryable admission failures stay queued and are retried by the service; callers do not receive `too_many_active_jobs` for that stage. Synchronous request throttling can still return `429`, conflicting request identity returns `409`, and unavailable sprite access can return `403`. Request validation and authentication happen before acceptance.

## Accepted jobs

A job that fails after acceptance reports a sanitized failure on its canonical `image_job`:

```json theme={null}
{
  "code": "generation_failed",
  "reason": "temporarily_unavailable",
  "message": "The service is temporarily unavailable. Please try again.",
  "retryable": true,
  "request_id": "018f3ef0-05f4-7c92-a6de-4ad4894f7b63"
}
```

The lowercase `code: generation_failed` is retained for older clients. New clients should use `reason` and `retryable`.

## Billing and retries

Image operations reserve one credit. Sprite requests reserve their complete approved price. A successful delivery settles that reservation once. Failure or timeout before delivery restores it once. Sprite requests do not offer customer cancellation. Duplicate callbacks, worker redelivery, and a repeated cancel cannot add another charge or restoration.

For retryable failures, first read the saved execution. If you still need to resend, use the original `Idempotency-Key` with the identical body. A new key can create new paid work.

Public errors never include provider or model names, private responses, prompts, filenames, asset URLs, credentials, stack traces, routing details, or internal database state.

`insufficient_frames` means the animation cannot supply enough distinct frames. The hold is restored; request fewer frames or use a different reference. No frames are silently duplicated or interpolated.

`prompt_policy_blocked` and `feature_unavailable` are reserved for restricted product hosts that share this API. Requests to the primary DreamLayer host never return them. Both are refused before any credit is reserved, so nothing is charged and there is nothing to retry with the same key.


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