Error codes
Errors are returned via HTTP status codes, machine-readable detail.error codes, and documented response shapes.
Status codes#
| Code | Name | Description |
|---|---|---|
400 | Bad Request | Invalid request. Unsupported model ID (with similar-model suggestions), model-specific parameter constraint violations (duration, resolution, reference image count, etc.), or a model outside the key's allowed set. |
401 | Unauthorized | Missing, invalid, or expired API key, or a deleted account. |
402 | Payment Required | Insufficient credits, exceeded budget/quota limits, or a BYOK suspension. The fix differs per code (see the machine-readable codes table below). |
403 | Forbidden | Access denied. Key IP allowlist violation, read-only scope, missing cross-border training consent, or an exceeded workspace limit. |
404 | Not Found | Resource not found. Unsupported model ID (single-model lookup), or a nonexistent usage log / job ID. |
409 | Conflict | A request with the same Idempotency-Key is already being processed. |
413 | Payload Too Large | Request body exceeds the limit (50MB by default). |
415 | Unsupported Media Type | Unsupported image or mask MIME type. |
422 | Unprocessable Entity | Request schema validation failure (field type or range violations). detail contains an array of locations and reasons. |
429 | Too Many Requests | Rate limit exceeded (60 RPM per key by default) or all upstreams rate-limited. Respect the Retry-After header. |
502 | Bad Gateway | Gateway error (the request did not reach the API server). The body may not be JSON — retry after a moment. |
503 | Service Unavailable | Upstream provider error, or temporarily unavailable (catalog snapshot unverifiable, limiter failure). For text requests an upstream error means automatic retries and fallback were exhausted; use the retryable field to decide whether retrying helps. |
Response shapes#
Error body shapes differ by surface. /v1/messages returns the Anthropic shape { type: "error", error: { type, message } }, and /v1beta returns the Google shape { error: { code, message, status } }. Other model APIs, such as Chat Completions and Responses, carry detail (string or object), and some responses also include the OpenAI-compatible { error: { message, type, code, param } } envelope. Schema validation failures (422) put an array in detail. Tell errors apart by the HTTP status code plus error.code or detail.
{
"error": {
"message": "사용 가능 크레딧 부족: 12,000 크레딧 < 54,000 크레딧. 대시보드 → 결제에서 충전해주세요.",
"type": "insufficient_quota",
"code": "insufficient_credits",
"param": null
},
"detail": {
"error": "insufficient_credits",
"message": "사용 가능 크레딧 부족: 12,000 크레딧 < 54,000 크레딧. 대시보드 → 결제에서 충전해주세요.",
"action": { "type": "topup", "path": "/billing" }
}
}{
"error": {
"message": "모델 제공자가 요청을 거부했습니다. 잠시 후 다시 시도하거나 다른 모델을 사용해주세요. (upstream 400: ...)",
"type": "api_error",
"code": "upstream_request_rejected",
"param": null
},
"detail": {
"error": "upstream_request_rejected",
"message": "모델 제공자가 요청을 거부했습니다. 잠시 후 다시 시도하거나 다른 모델을 사용해주세요. (upstream 400: ...)",
"retryable": false,
"upstream": { "status": 400, "detail": "..." }
}
}{
"error": {
"message": "요청 본문이 너무 큽니다(최대 50MB).",
"type": "payload_too_large"
}
}{
"detail": [
{
"type": "greater_than_equal",
"loc": ["body", "duration_seconds"],
"msg": "Input should be greater than or equal to 2",
"input": 1,
"ctx": {"ge": 2}
}
]
}Structured errors may include an action field with a dashboard path, plus retryable, providers, and upstream where applicable. message is always Korean — treat it as human guidance, not a parsing target.
Machine-readable codes#
| Code | Location · HTTP | Meaning and fix |
|---|---|---|
insufficient_credits | error.code · detail.error · 402 | Insufficient credits. Top up on the dashboard's Billing page, then retry. |
request_exceeds_credits | error.code · detail.error · 402 | The balance cannot cover this request's maximum cost. The message states how many tokens you can afford. Lower max_tokens or top up, then retry. |
monthly_budget_exceeded | error.code · detail.error · 402 | Key daily, weekly, or monthly budget exceeded. Adjust the budget in key settings, not by topping up. |
monthly_token_quota_exceeded | error.code · detail.error · 402 | Key monthly token quota exceeded. Adjust the quota in key settings. |
byok_suspended | error.code · detail.error · 402 | BYOK calls are suspended for an unpaid BYOK charge. Topping up lifts the suspension automatically. |
workspace_budget_exceeded | error.code · detail.error · 403 | Workspace limit exceeded. Ask the workspace owner to adjust the limit. details names the period that hit the limit. |
xborder_training_consent_required | error.code · detail.error · 403 | Missing separate consent for training-use providers. Returned with a providers list; consent in Settings resolves it. |
guardrail_blocked | error.code · detail.error · 403 | Request blocked by a guardrail policy. The guardrail field carries the policy name. Edit the request content. |
rate_limit_exceeded | error.code · 429 | Request rate limit exceeded. The default code for a 429 that carries no other code. Retry after Retry-After. |
admission_busy | error.code · detail.error · 429 | Temporarily rejected while concurrent in-flight requests reserve balance. Not an insufficient-balance error (402); retry after Retry-After. |
concurrency_limit_exceeded | error.code · detail.error · 429 | Per-user concurrent request limit exceeded. Retry once in-flight requests finish. |
upstream_rate_limited | error.code · detail.error · 429 | All upstreams rate-limited. Retry after Retry-After. |
upstream_unavailable | error.code · detail.error · 503 | Transient upstream failure (retryable=true). Retry after a moment. |
upstream_request_rejected | error.code · detail.error · 503 | Upstream rejected the request (retryable=false). Fix the request or switch models. The upstream field carries a summary. |
catalog_snapshot_stale | error.code · detail.error · 503 | Catalog snapshot unverifiable. Retry after a moment. |
provider_unavailable | error.code · detail.error · 503 | The model's provider connection has a platform-side problem. Retry later or use another model. |
upstream_error | SSE error.code | Upstream dropped mid-stream (SSE). partial is a boolean; when true, only the part already received is billed. |
invalid_request | error.type · 400 | Malformed request value (e.g. a non-UUID where a UUID is expected). |
payload_too_large | error.type · 413 | Request body exceeds the limit. |
limiter_unavailable | error.type · 503 | Transient limiter failure. Retry after a moment. |
Errors during streaming#
A stream: true request that fails mid-stream still returns HTTP 200, so the failure arrives as an SSE event. partial is a boolean. When true, part of the response was already received and only that part is billed; a usage chunk follows, then data: [DONE]. When false, nothing was received and data: [DONE] follows immediately.
data: {"error": {"code": "upstream_error", "type": "api_error", "message": "모델 제공자 연결이 중단되었습니다. 받은 부분까지만 과금됩니다.", "partial": true}}
data: {"id":"chatcmpl-abc","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: {"choices":[],"usage":{"prompt_tokens":12,"completion_tokens":3,"total_tokens":15}}
data: [DONE]Retry guidance#
Retry 429 and 503 (retryable=true) with exponential backoff. The text path already retries providers twice and falls back, so we recommend a client retry interval of at least 1 second. 4xx and retryable=false 503 keep failing until you fix the request.
retryable=true, immediately retrying the identical request may yield the same result; check your parameters first.Common errors and fixes#
| Error | Fix |
|---|---|
400 — unsupported model ID (typo such as gpt-5.5-mini) | The message includes similar-model suggestions. Check the full list via GET /v1/models. |
| 400/422 — media parameter rejected (duration, resolution, reference count, etc.) | Check the per-model constraint tables in the media docs (Images, Video). The error message names the rejected parameter and its allowed values. |
| 402 — insufficient_credits | Top up on the dashboard's Billing page and retry. For budget/quota codes, adjust the limit in key settings instead. |
| 429 — rate limit | Retry with exponential backoff after the Retry-After header value. |
| 503 — upstream_request_rejected | Inspect the upstream summary, check your request parameters, and switch models if the result repeats. |