# Errors

> The error envelope, request ids and every status and error code the API returns.

Source: https://useprimitives.com/docs/api/errors

Every error returns a non-2xx status and the same JSON envelope:

```json
{
  "error": {
    "code": "branch_conflict",
    "message": "Main database changed since branch 'try-migration' was created."
  }
}
```

Every response carries an `X-Request-Id` header. Include it when you contact support.

| Status | Code | Meaning |
| --- | --- | --- |
| 400 | `invalid_request` | The body or parameters failed validation, the SQL is invalid, or an operation ran past its 10-second time limit and was stopped. |
| 400 | `wrong_type` | The data route doesn't apply to this primitive's type, such as `query` on a filesystem. The message names its type. |
| 401 | `invalid_token` | The API key or token is missing, malformed, revoked or expired. |
| 403 | `forbidden` | The caller can't do this, such as a scoped API key calling an account endpoint, or a write through a read-only key. |
| 403 | `group_mismatch` | The path or `X-Primitives-Group` header names a group outside the API key's scope. |
| 403 | `plan_limit` | The workspace's plan doesn't include this, such as a second group on Starter, a snapshot, restore or fork on Starter, or the audit log on Starter. |
| 403 | `tool_not_allowed` | The API key's tool allowlist doesn't cover this endpoint. |
| 403 | `secret_policy_denied` | The request is outside the secret's grant, there is no grant, or the destination is blocked. |
| 404 | `not_found` | The group, primitive, file, job, memory, key, object, branch or snapshot doesn't exist, or the primitive is outside the API key's group. The message names it. |
| 409 | `already_exists` | A group or branch with that name exists, or the group already has a primitive of that type with that name. |
| 409 | `conflict` | The request conflicts with current state, such as a constraint violation, requeueing a job that isn't dead, or deleting a non-empty group without `?force=true`. |
| 409 | `branch_conflict` | The main database changed since the branch was created. |
| 409 | `fs_conflict` | A file or directory is in the way, or a directory isn't empty. |
| 405 | `method_not_allowed` | Cloud only. A [signed URL](/docs/api/signed-urls) was called with a method it doesn't accept. |
| 410 | `lease_expired` | The queue lease ran out before the job was settled. |
| 410 | `secret_grant_expired` | The secret's grant has expired. |
| 412 | `precondition_failed` | A condition didn't hold: a key's `if_version` didn't match, or an object's `If-Match` / `If-None-Match` failed. Nothing was written. |
| 413 | `payload_too_large` | The request body, a file, object, key value or secret value exceeds its limit, or the primitive reached its storage limit. |
| 416 | `range_not_satisfiable` | The `Range` of an object read starts past its end. |
| 423 | `paused` | The primitive is paused. Resume it to read or write its data. |
| 429 | `plan_limit` | A Starter workspace reached its monthly operations cap, its storage cap on a write, or its 100-primitive cap on a create. See [Usage and limits](/docs/api/limits#usage-and-limits). |
| 429 | `rate_limited` | Too many requests, or the server is busy, such as too many exports at once. See [Rate limits](/docs/api/limits#rate-limits). |
| 500 | `internal_error` | Something went wrong on our side. Safe to retry. |
| 501 | `multi_region_unsupported` | Cloud only. A workspace-wide [audit](/docs/api/audit) read on a workspace with groups in more than one region. Read it per group. |
| 502 | `upstream_error` | The upstream request made by a vault's `fetch` failed or timed out. |
| 502 | `engine_unavailable` | Cloud only. The API couldn't reach the engine that holds the group. Retry shortly. |
| 503 | `region_unavailable` | Cloud only. The region that holds the group is unavailable. Retry later. |
