Reference
Error catalog
Every typed error code the Calypso public API returns, in one table — with the shared envelope, retryability, and the endpoints that raise each.
The error envelope
Every error from the search, ingest, and manage surfaces uses one shape. code is machine-stable, retryable tells you whether backing off and retrying can succeed, and request_id (also echoed in the X-Request-Id header) is what to quote in support requests:
{
"error": {
"code": "bucket_not_found",
"message": "Bucket not found or not active: docs",
"retryable": false,
"details": { "bucket": "docs" }
},
"request_id": "req_abc123"
}
The exception is the OpenAI-compatible ask endpoints (/v1/responses, /v1/chat/completions, /v1/models): they return OpenAI-style errors ({"error": {"code", "message", "type"}}) so stock SDK error handling keeps working — no top-level request_id or retryable field there.
Auth & authorization
| Status | Code | Retryable | Meaning |
|---|---|---|---|
| 401 | invalid_project_key | no | The key is missing, malformed (keys start with sk-), or inactive. |
| 403 | forbidden_project_key | no | The key lacks a required capability — details.required_capability names it. See Capabilities. |
Ingestion
| Status | Code | Retryable | Meaning |
|---|---|---|---|
| 400 | bucket_required | no | No destination bucket (legacy body-addressed routes only — impossible on /v1/buckets/{bucket}/… paths). |
| 404 | bucket_not_found | no | The bucket does not exist or is archived. |
| 400 | bucket_assignment_failed | no | A named bucket could not be resolved or assigned. |
| 409 | bucket_slug_exists | no | Bucket create collided on slug without a matching Idempotency-Key. |
| 400 | empty_file | no | Zero-byte upload. |
| 413 | file_too_large | no | Over the 25 MB cap (details.max_bytes). |
| 422 | url_is_web_page | no | File import got HTML — cross-referral to /pages; force: true overrides. |
| 422 | url_is_file | no | Page ingestion got a document URL — cross-referral to files/import; force: true overrides. |
| 400 | url_fetch_blocked | no | URL rejected by fetch policy. |
| 502 | url_fetch_failed | yes | The remote host failed to serve the file. |
| 409 | website_url_exists | no | The page URL already exists for this team (details carry the source id). |
| 502 | website_analysis_failed | yes | Page crawl or analysis failed. |
| 409 | idempotency_key_conflict | no | The same Idempotency-Key was reused with a different request body. |
| 400 | invalid_idempotency_key | no | The Idempotency-Key was empty, over length, or contained non-visible-ASCII characters. |
| 409 | request_in_progress | yes | An identical request with this Idempotency-Key is still running. Back off and retry — the retry replays the original result once it settles. |
| 409 | team_store_maintenance | yes | The team's search store is being rebuilt. Honor details.retry_after_seconds and retry. |
Readiness & retrieval
| Status | Code | Retryable | Meaning |
|---|---|---|---|
| 409 | bucket_store_indexing_pending | yes | The bucket has no indexed content yet — wait for the first source to become ready. |
| 404 | model_not_found | no | The requested model/agent id is not a Calypso agent id. |
| 404 | agent_not_found | no | The named agent does not exist. |
| 504 | search_timeout | yes | /v1/search exceeded its latency budget. |
| 502 | search_failed | yes | The search provider failed to serve the query. |
| 503 | search_disabled | yes | /v1/search is temporarily disabled for maintenance. |
Deletion
| Status | Code | Retryable | Meaning |
|---|---|---|---|
| 409 | delete_blocked | no | The target has dependents — a source with references, or an agent the team's widget is bound to (details.bound_surface). Pass force=true to override. |
| 400 | force_required | no | Destructive cascades (DELETE /v1/buckets/{bucket}) must be confirmed with force=true. |
| 409 | delete_in_progress | yes | A delete cascade for this bucket is already running. Retry after it finishes: 404 if the cascade completed, 200 (re-running the cascade) if a partial failure restored the bucket. |
| 400 | metadata_filter_too_large | no | A search over an explicit-id scope exceeded the provider filter limit — switch the agent to bucket scope. |
Quotas & limits
| Status | Code | Retryable | Meaning |
|---|---|---|---|
| 429 | rag_quota_exceeded | no (until reset) | The workspace reached its plan's answer limit (asks and searches both count). |
| 402 | agent_limit_reached | no | The plan's named-agent cap is reached. |
| 400 | no_updates | no | PUT /v1/agents/{agent_id} needs at least one field to update. |
| 400 | invalid_agent_profile | no | The agent update failed schema validation (details.errors). |
| 503 | agent_replay_check_unavailable | yes | Agent create hit an id collision but could not confirm whether it was your own idempotent replay. Retry with the same Idempotency-Key. |
| 429 | upload_rate_limited | yes | Ingestion creates are limited to 5 requests/second/team. Honor the Retry-After header (details.retry_after_seconds) and retry. |
Server
| Status | Code | Retryable | Meaning |
|---|---|---|---|
| 500 | internal_error | no | Unexpected server error — include request_id when reporting. |
Handling guidance
- Branch on
code, never onmessage— messages can change, codes do not. - Respect
retryable: retry with backoff whentrue, fix the request whenfalse. - Cross-referral errors (
url_is_web_page,url_is_file) are navigational: followdetails.suggested_endpointrather than treating them as failures.