# Errors

The Layer REST API uses conventional HTTP status codes and returns a consistent, machine-readable error body following [RFC 7807 Problem Details](https://datatracker.ietf.org/doc/html/rfc7807).

## Error shape

Errors are returned with the `application/problem+json` content type and this shape:

```json
{
  "type": "https://api.layer.ai/errors/WORKSPACE_NOT_FOUND",
  "title": "Workspace not found",
  "status": 404,
  "detail": "Workspace 2489e9ad-… doesn't exist or you're not a member."
}
```

* **`type`** — a stable URI ending in the machine-readable error code. Branch on this (or the trailing code), not on the human-readable `title`.
* **`status`** — mirrors the HTTP status.
* **`detail`** — a human-readable explanation. For `4xx` errors this is specific; for `5xx` errors it’s scrubbed to a generic message.

## Error codes

| Code                  | Status | Meaning                                                                          |
| --------------------- | ------ | -------------------------------------------------------------------------------- |
| UNAUTHENTICATED       | 401    | Missing or invalid bearer token. See [Authentication](/docs/authentication).     |
| FORBIDDEN             | 403    | The authenticated user lacks permission for this action or workspace.            |
| INSUFFICIENT\_BALANCE | 402    | Not enough Creative Units. See [Creative Units & billing](/docs/creative-units). |
| RATE\_LIMITED         | 429    | Too many requests. See [Rate limits](/docs/rate-limits).                         |
| WORKSPACE\_NOT\_FOUND | 404    | Workspace doesn’t exist or you’re not a member.                                  |
| MODEL\_NOT\_FOUND     | 404    | Model not found or not available in this workspace.                              |
| WORKFLOW\_NOT\_FOUND  | 404    | Workflow not found or not linked to this workspace.                              |
| INFERENCE\_NOT\_FOUND | 404    | Inference (forge) run doesn’t exist.                                             |
| RUN\_NOT\_FOUND       | 404    | Workflow run doesn’t exist.                                                      |
| INVALID\_INPUTS       | 422    | Malformed parameters, UUIDs, or an invalid pagination cursor.                    |
| UPLOAD\_FAILED        | 502    | A file could not be downloaded or stored.                                        |
| INTERNAL\_ERROR       | 500    | An unexpected server error. Retry later; contact support if it persists.         |

## Asynchronous failures

Generation is [asynchronous](/docs/async-jobs), and **not every failure surfaces as an HTTP error**. In particular, your Creative Unit balance is **not** checked when you submit a run: an underfunded run is accepted with `202` and later reaches a terminal `FAILED`/`FAILURE` state carrying `error_code: INSUFFICIENT_BALANCE`.

Caution

Always check the terminal status and `error_code` of a run when you poll it — a `202` on submit does not guarantee success. [Estimate](/docs/creative-units) before you execute to avoid this.

## Handling errors

* Retry `429` after the `Retry-After` interval, and `5xx` with exponential backoff.
* Do **not** blindly retry `4xx` errors other than `429` — fix the request first.
* Because the API has [no idempotency keys](/docs/integration-notes), a retry of an _execute_ request that actually succeeded server-side will create a **duplicate run**. Prefer polling an existing run over re-submitting.
