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

# Errors

> Framelane uses structured error codes in all error responses.

## Error shape

All API errors follow this JSON envelope:

```json theme={null}
{
  "error": {
    "code": "not_found",
    "message": "Render not found.",
    "details": {}
  }
}
```

| Field     | Type   | Description                                   |
| --------- | ------ | --------------------------------------------- |
| `code`    | string | Machine-readable error code (see table below) |
| `message` | string | Human-readable description                    |
| `details` | object | Optional additional context                   |

## Validation errors

When a request fails schema validation (`code: "invalid_request"`, HTTP `422`),
`details.errors` lists each problem. **Unknown fields are rejected, not silently
ignored** — a typo like `font_wight` fails loudly instead of being dropped, so an
edit never appears to succeed while changing nothing.

```json theme={null}
{
  "error": {
    "code": "invalid_request",
    "message": "Request validation failed.",
    "details": {
      "errors": [
        {
          "type": "extra_forbidden",
          "loc": ["body", "elements", 0, "text", "font_wight"],
          "msg": "Extra inputs are not permitted",
          "pointer": "/elements/0/font_wight",
          "suggestion": "font_weight"
        }
      ]
    }
  }
}
```

| Field        | Type   | Description                                                                                                                   |
| ------------ | ------ | ----------------------------------------------------------------------------------------------------------------------------- |
| `type`       | string | Machine-readable failure kind (`extra_forbidden`, `enum`, `missing`, …).                                                      |
| `loc`        | array  | pydantic location path (includes the union-variant tag for element errors).                                                   |
| `msg`        | string | Human-readable explanation.                                                                                                   |
| `pointer`    | string | [RFC 6901](https://datatracker.ietf.org/doc/html/rfc6901) JSON pointer to the offending value, e.g. `/elements/0/font_wight`. |
| `suggestion` | string | Present when a close valid field name or enum value exists — "did you mean `font_weight`?". Advisory.                         |

`suggestion` is omitted when there is no close match, and for a *misplaced* real
field (e.g. `duration` on a `video` element — use `out_point` for clip length),
where a fuzzy guess would mislead. Structurally-impossible project ops
(`POST /v1/projects/{id}/ops`) also carry a `pointer` in `details`, e.g. `/ops/0`.

## HTTP status codes

| Status | Meaning                                               |
| ------ | ----------------------------------------------------- |
| `200`  | OK                                                    |
| `202`  | Accepted — job enqueued                               |
| `201`  | Created                                               |
| `204`  | No content                                            |
| `400`  | Bad request                                           |
| `401`  | Unauthorized — invalid or missing API key             |
| `403`  | Forbidden                                             |
| `404`  | Not found                                             |
| `409`  | Conflict — idempotency key reused with different body |
| `422`  | Unprocessable entity — validation failed              |
| `429`  | Too many requests — rate limit exceeded               |
| `500`  | Internal server error                                 |

## Error codes

| Code                  | HTTP | Description                                                                                                        |
| --------------------- | ---- | ------------------------------------------------------------------------------------------------------------------ |
| `unauthorized`        | 401  | Missing or invalid API key                                                                                         |
| `forbidden`           | 403  | Action not permitted for this workspace                                                                            |
| `not_found`           | 404  | Resource does not exist                                                                                            |
| `conflict`            | 409  | Idempotency key conflict                                                                                           |
| `invalid_request`     | 422  | Request validation failed                                                                                          |
| `unsupported_feature` | 422  | Feature not yet supported                                                                                          |
| `invalid_source`      | 422  | Source URL is invalid or inaccessible                                                                              |
| `source_not_found`    | 422  | Source URL returned 404                                                                                            |
| `source_too_large`    | 422  | Source file exceeds the 5 GiB limit                                                                                |
| `asset_not_ready`     | 422  | Referenced media is still being processed (retry after the `asset.ready` webhook)                                  |
| `ingest_failed`       | —    | A public file referenced with `ingest_external` could not be copied into Framelane storage (set on the failed job) |
| `codec_unsupported`   | 422  | Codec not supported by the render engine                                                                           |
| `quota_exceeded`      | 429  | Monthly render or task quota exhausted                                                                             |
| `rate_limited`        | 429  | Too many requests in the current window                                                                            |
| `internal`            | 500  | Unexpected internal error                                                                                          |

## Job-level errors

When a render or task fails asynchronously, the `error` field is set on the job object:

```json theme={null}
{
  "id": "render_01J...",
  "status": "failed",
  "error": {
    "code": "source_not_found",
    "message": "Source URL returned 404: https://cdn.example.com/missing.mp4"
  }
}
```

The same error is included in the `render.failed` / `task.failed` webhook payload.
