# Errors (/docs/api/errors)



Every error response uses a single JSON envelope with a stable,
machine-readable code. Branch on the `code` field, not on the
human-readable message, which may change.

## Error envelope [#error-envelope]

All error responses share this shape:

```json
{
  "error": {
    "code": "invalid_request",
    "message": "ttlMs must be a positive integer",
    "details": { "field": "ttlMs" }
  }
}
```

* `code` — lowercase snake\_case identifier, stable across releases.
* `message` — human-readable explanation, for logs and debugging.
* `details` — optional object with extra context, varies by code.

## Error codes [#error-codes]

These are the error codes you can encounter across the public API:

| Code                              | HTTP    | Meaning                                             |
| --------------------------------- | ------- | --------------------------------------------------- |
| `invalid_request`                 | 400     | Malformed request or validation failure             |
| `sandbox_ttl_exceeded`            | 400     | Requested `ttlMs` exceeds your plan limit           |
| `reserved_env_key`                | 400     | Env key uses the reserved `CROWNEST` prefix         |
| `unauthorized`                    | 401     | Missing or invalid credentials                      |
| `invalid_api_key`                 | 401     | API key is malformed or revoked                     |
| `forbidden`                       | 403     | Missing scope or no access to the resource          |
| `org_suspended`                   | 403     | Organization is suspended                           |
| `not_found`                       | 404     | Resource doesn't exist or isn't visible to your key |
| `idempotency_key_reused`          | 409     | Same `Idempotency-Key` with a different request     |
| `idempotency_request_in_progress` | 409     | Original request with this key is still running     |
| `sandbox_destroyed`               | 409     | Sandbox is already destroyed                        |
| `file_too_large`                  | 413     | File exceeds the 256 KB direct read/write limit     |
| `quota_exceeded`                  | 429     | Plan quota reached                                  |
| `rate_limited`                    | 429     | Request rate limit reached                          |
| `stream_gap`                      | 409     | Log sequence is outside the retention window        |
| `resource_allocation_failed`      | 500/503 | Internal resource allocation or startup failed      |
| `unsupported_runtime_option`      | 500     | Runtime option or placement is not supported        |
| `preview_unavailable`             | 502     | Preview port isn't responding                       |

File operations have additional codes such as `path_outside_workspace`,
`file_not_found`, and `directory_not_empty`. See
[Files](/docs/api/files#file-error-codes) for the full list.

<Callout type="info" title="Note">
  A non-zero command exit code is not an API error. The HTTP request succeeds, and you
  read the outcome from the Command object's `status` and `exitCode` fields.
</Callout>

## Handling 4xx errors [#handling-4xx-errors]

A 4xx response means the request itself is the problem. Don't retry the
same request unchanged — fix it first:

* `invalid_request`, `sandbox_ttl_exceeded`, `reserved_env_key` — correct
  the request body or parameters.
* `unauthorized`, `invalid_api_key`, `forbidden` — fix the credential or
  its scopes. See [Authentication](/docs/api/authentication).
* `not_found`, `sandbox_destroyed` — the resource is gone or invisible to
  your key; don't retry.
* `quota_exceeded` and `rate_limited` are the exception: both return 429
  and are retryable. For `rate_limited`, retry after a short backoff. For
  `quota_exceeded`, free up capacity (for example, kill idle sandboxes) or
  upgrade your plan.

## Handling 5xx errors [#handling-5xx-errors]

A 5xx response means something failed on the server side. These are
generally safe to retry with exponential backoff. For POST endpoints that
create or run resources, retry with the same `Idempotency-Key` so a retry
can never duplicate work. See
[Pagination and idempotency](/docs/api/pagination-and-idempotency).

## Next steps [#next-steps]

* Make retries safe in
  [Pagination and idempotency](/docs/api/pagination-and-idempotency).
* Review file-specific codes in [Files](/docs/api/files).
