---
title: Errors
description: The stable error codes of the pols API, CLI, MCP server and TypeScript client, what usually causes each, and what to do.
---

Every failed API call returns a JSON body with a stable, machine-readable `code` and a human-readable `message`:

```json
{ "error": { "code": "quota_exceeded", "message": "..." } }
```

The CLI prints the message, and with `--json` it prints the same document. The TypeScript client throws a `PolsError` with `status` and `code`. Match on `code`, never on the message text.

| Code | HTTP | Usually means | What to do |
| --- | --- | --- | --- |
| `bad_request` | 400 | an invalid argument: size, name, CIDR, path, coordinates, or a vault entry that does not exist | fix the input; add a missing vault entry on the account page |
| `unauthorized` | 401 | no API key, a wrong one, or a revoked or expired one | run `pols login` or set `POLS_API_KEY` |
| `forbidden` | 403 | the action is not allowed, such as deleting the system template or managing API keys with an API key | use your own template; manage keys on the account page |
| `quota_exceeded` | 403 | too many running or existing sandboxes or templates, the monthly hours are used up, or the host has no room for this size | stop or delete something, or try a smaller size; see [quotas](/getting-started/limits/#quotas) |
| `not_found` | 404 | a wrong ID or name, or a file that does not exist | check `pols ls` or the path |
| `conflict` | 409 | the sandbox is not running, is still in a transition, or the name is taken | `pols get` it, wait until it has arrived or resume it, or pick another name |
| `rate_limited` | 429 | too many requests, failed logins, or calls in progress at once | wait the `Retry-After` seconds and retry with fewer parallel calls; see [rate limits](/getting-started/limits/#rate-limits) |
| `internal` | 500 | a bug or an outage on our side | retry later; tell us if it persists |
| `runtime_error` | 502 | the sandbox host failed to carry out the call | retry; a sandbox in status `error` has to be deleted |
| `unavailable` | 503 | the feature is not configured on this deployment, such as the vault, ports, desktop links or SSH | use `pols exec` and `pols cp` instead, or ask us |
| `timeout` | 504, 408 | the sandbox host was too slow, or a request body stalled for 30 seconds | retry |

## Sandbox errors

Separate from API errors, a sandbox whose transition failed goes to status `error`, with the reason in `last_error`. It cannot be used any more: delete it and create a new one, or fork an earlier copy if you have one.

## Exit codes

A command that runs in a sandbox and exits with a non-zero code is not an API error. `pols exec` exits with the same code, the API returns it in `exit_code`, and the MCP tool `sandbox_exec` returns it as a normal result.
