> For the complete documentation index, see [llms.txt](https://docs.roboflow.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.roboflow.com/reference/errors-and-status-codes.md).

# Errors and Status Codes

Roboflow's developer tools share a small set of error categories, surfaced differently in each tool. This page is the cross-cutting reference.

## CLI exit codes

The CLI uses four well-defined exit codes so scripts and AI agents can branch on outcome without parsing output:

| Exit code | Meaning                                                                                                      |
| --------- | ------------------------------------------------------------------------------------------------------------ |
| `0`       | Success                                                                                                      |
| `1`       | General error (bad input, network failure, unexpected server response)                                       |
| `2`       | Authentication failure (missing or invalid API key, no workspace selected)                                   |
| `3`       | Resource not found (project, version, workflow, deployment, etc. doesn't exist or isn't visible to your key) |

In `--json` mode the CLI writes structured output to stdout on success and a JSON error object to stderr on failure, leaving stdout empty so pipelines stay safe to parse:

```bash
roboflow --json project get nonexistent 2>error.json
echo $?       # 3
cat error.json
# {"error": {"message": "Project 'nonexistent' not found", "hint": "Run 'roboflow project list' to see your projects."}}
```

## SDK exceptions

The Python SDK raises Python exceptions on failure. The most common types you'll encounter:

| Exception                                            | When                                                                                                                                              |
| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `RuntimeError`                                       | Operation is logically invalid - e.g., calling `restore()` on a project that isn't in Trash, or training on a version that hasn't been generated. |
| `ValueError`                                         | A passed argument is malformed - e.g., an unrecognized `model_format` for `Version.download()`.                                                   |
| `roboflow.adapters.rfapi.RoboflowError`              | The REST API returned a non-2xx response. The exception's string contains the server's error body.                                                |
| `roboflow.adapters.deploymentapi.DeploymentApiError` | Equivalent to `RoboflowError` for the dedicated-deployments service.                                                                              |
| `requests.exceptions.HTTPError` / `ConnectionError`  | Network-level failures (DNS, TLS, timeout).                                                                                                       |

Rule of thumb: catch `RuntimeError` for logical issues, `RoboflowError` for server-side rejections, and let everything else bubble.

```python
from roboflow.adapters import rfapi

try:
    project.restore()
except RuntimeError as e:
    print(f"Can't restore: {e}")
except rfapi.RoboflowError as e:
    print(f"Server rejected the request: {e}")
```

See [Logging and Debugging](/reference/python-sdk/python-sdk/logging-and-debugging.md) for how to inspect the underlying HTTP request when an exception isn't enough.

## REST API status codes

The REST API uses standard HTTP status codes. Roboflow-specific behavior:

| Status | Meaning                                                                                                                                                                                                                                                                                                            |
| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `200`  | Success. Response body is JSON.                                                                                                                                                                                                                                                                                    |
| `204`  | Success, no body (used for some `PATCH` / `DELETE` endpoints).                                                                                                                                                                                                                                                     |
| `400`  | Malformed request - missing required field, bad shape, invalid value.                                                                                                                                                                                                                                              |
| `401`  | Authentication failure. Either no `api_key`, an invalid one, or a key that lacks the required scope for the operation.                                                                                                                                                                                             |
| `402`  | Payment required. The workspace's plan does not support the requested operation. For inference, this means the model or architecture is only available on a credit-based plan, or the workspace's monthly Hosted API inference quota has been reached. The response body includes an `AccessException` error type. |
| `403`  | Forbidden. The key authenticated but doesn't have access to the target workspace or resource.                                                                                                                                                                                                                      |
| `404`  | Not found. The workspace, project, version, workflow, or other resource doesn't exist (or isn't visible to your key).                                                                                                                                                                                              |
| `409`  | Conflict. The resource exists in a state that prevents the requested operation (for example, restoring a version whose parent project is also in Trash).                                                                                                                                                           |
| `423`  | Locked. Workspace billing is paused - see the response body for the reason.                                                                                                                                                                                                                                        |
| `429`  | Rate limited. Slow down and retry with exponential backoff.                                                                                                                                                                                                                                                        |
| `5xx`  | Server error. Safe to retry with backoff.                                                                                                                                                                                                                                                                          |

### Standard error body

Errors return JSON with at least a top-level `error` field:

```json
{
  "error": "Project 'nonexistent' not found"
}
```

Some endpoints also include a `hint` or a structured error object - see the per-endpoint documentation under [REST API](/reference/rest-api/rest-api/using-the-rest-api.md) for specifics.

### Required scopes

API keys carry per-resource scopes. A 401 from a write operation often means the key doesn't have the corresponding `*:update` or `*:write` scope, even if it can read the resource. See [Scoped API Keys](/reference/authentication/authentication/scoped-api-keys.md) for the scope reference.

## Cross-tool error mapping

| Situation                        | CLI exit | SDK                                      | REST  |
| -------------------------------- | -------- | ---------------------------------------- | ----- |
| Missing / invalid API key        | `2`      | `RoboflowError` ("401")                  | `401` |
| Resource not found               | `3`      | `RoboflowError` ("404") / `RuntimeError` | `404` |
| Plan limitation / quota exceeded | `1`      | `RoboflowError` ("402")                  | `402` |
| Bad input / malformed request    | `1`      | `ValueError` / `RoboflowError` ("400")   | `400` |
| Server error / transient         | `1`      | `RoboflowError` ("5xx")                  | `5xx` |

Use this table when wiring retries: a `2` / 401 should never be retried automatically (the key won't get more valid), a `3` / 404 should never be retried, but a `1` from a 5xx response is a candidate for retry with backoff.
