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

# Errors

> Handle one structured JSON error envelope across OrgX REST API v1.

Errors use one envelope:

```json theme={"dark"}
{
  "error": {
    "code": "validation_failed",
    "message": "Title is required",
    "details": { "field": "title" },
    "requestId": "req_01J5YB8X4Y",
    "timestamp": "2026-08-18T18:30:00.000Z"
  }
}
```

Branch on the HTTP status and `error.code`. When `requestId` is present, log it
and include it when you contact support.

| Status | Meaning                                       | Retry                                       |
| ------ | --------------------------------------------- | ------------------------------------------- |
| `400`  | Invalid request                               | Fix the request                             |
| `401`  | Missing or invalid authentication             | Fix or rotate the key                       |
| `403`  | The caller lacks permission                   | Change scope or access                      |
| `404`  | The resource is unavailable in this workspace | Check the ID and workspace                  |
| `409`  | State or idempotency conflict                 | Read current state before deciding          |
| `413`  | Request exceeds the documented size           | Reduce the body                             |
| `422`  | The JSON fails the resource schema            | Fix the reported issue paths                |
| `429`  | Rate limit reached                            | Honor `Retry-After`                         |
| `500`  | Unexpected server error                       | Retry only with an idempotency key          |
| `503`  | A required service is temporarily unavailable | Back off and retry                          |
| `504`  | A dependency timed out                        | Retry reads; retry writes with the same key |

Validation endpoints may add bounded `issues` with JSON Pointer paths. The
outer `error` envelope remains the programmatic contract.

## Error codes

Codes are lowercase `snake_case`. The shared vocabulary is:

| Code                       | Status | Meaning                                        |
| -------------------------- | ------ | ---------------------------------------------- |
| `bad_request`              | 400    | The request format is invalid                  |
| `validation_failed`        | 400    | The request failed schema validation           |
| `unauthorized`             | 401    | Auth is missing or invalid                     |
| `forbidden`                | 403    | The caller lacks permission                    |
| `not_found`                | 404    | The resource does not exist here               |
| `conflict`                 | 409    | State conflict                                 |
| `budget_exceeded`          | 402    | Autonomy budget depleted                       |
| `plan_limit_reached`       | 403    | Plan quota exceeded                            |
| `rate_limited`             | 429    | Too many requests                              |
| `internal_error`           | 500    | Unexpected server error                        |
| `integration_error`        | 502    | An external service failed                     |
| `service_unavailable`      | 503    | A dependency is unavailable                    |
| `timeout`                  | 504    | The request timed out                          |
| `missing_idempotency_key`  | 400    | A mutation did not include `Idempotency-Key`   |
| `idempotency_key_conflict` | 409    | The key was reused with a different payload    |
| `lifecycle_action_failed`  | 422    | The requested lifecycle transition was refused |

Individual resources add their own codes on top of these — for example
`missing_idempotency_key`, `handoff_conflict`, `operating_process_conflict`,
`discovery_run_in_progress`, `invalid_agent_work_receipt`, and
`direct_human_decision_action_required`. Mutations also use
`idempotency_key_conflict` for retry protection. Those are documented on each
resource's page. Branch on the HTTP status first and the code second, so an
unfamiliar resource-specific code still routes to the right handling.

## The MCP tool surface uses a different vocabulary

MCP tool errors are **not** these codes. That surface has its own set —
`invalid_input`, `auth_required`, `permission_denied`, `entity_not_found`,
`stale_version`, `rate_limit_exceeded`, `server_error`, and others —
documented in the [failure playbooks](/docs/agent-ops/failure-playbooks). The two
vocabularies are not aliases of each other; do not map one onto the other in
client code.

| Condition               | REST v1                                          | MCP tools             |
| ----------------------- | ------------------------------------------------ | --------------------- |
| Validation failed       | `validation_failed`                              | `invalid_input`       |
| Auth missing or invalid | `unauthorized`                                   | `auth_required`       |
| Caller lacks permission | `forbidden`                                      | `permission_denied`   |
| Resource not found      | `not_found`                                      | `entity_not_found`    |
| Concurrency conflict    | `conflict` (or a resource-specific `*_conflict`) | `stale_version`       |
| Rate limited            | `rate_limited`                                   | `rate_limit_exceeded` |
| Unexpected server error | `internal_error`                                 | `server_error`        |

Retry timing differs with the surface too: REST v1 sends `Retry-After`; the
MCP edge sends `X-RateLimit-Reset` alongside `X-RateLimit-Limit` and
`X-RateLimit-Remaining`. Honor whichever the response you are holding carries.
