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:
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.
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 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:
{
"error": "Project 'nonexistent' not found"
}Some endpoints also include a hint or a structured error object - see the per-endpoint documentation under REST API 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 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.