Error Reference
All gateway errors follow the OpenAI-compatible error format. This page documents every error type, code, and HTTP status code the gateway can return.
Error format
{
"error": {
"message": "Human-readable error description",
"type": "error_type_category",
"param": null,
"code": "machine_readable_code"
}
}| Field | Type | Description |
|---|---|---|
message | string | Human-readable description of the error |
type | string | Error category (see Error types below) |
param | string or null | The request parameter that caused the error, if applicable |
code | string | Machine-readable error code for programmatic handling |
Error types
| Type | Description |
|---|---|
invalid_request_error | The request was malformed or missing required fields |
authentication_error | API key is missing, invalid, expired, or rotated |
permission_error | The request was blocked by a governance policy |
rate_limit_error | The organization has exceeded its rate limit |
insufficient_quota | The organization has exceeded its plan quota |
not_found_error | The requested resource does not exist |
upstream_error | The upstream LLM provider returned an error |
gateway_error | Internal gateway error |
timeout_error | The upstream provider timed out |
connection_error | Failed to connect to the upstream provider |
service_unavailable | The provider is temporarily unavailable (circuit breaker open) |
HTTP status codes
| Code | Type | When |
|---|---|---|
200 | Success | Request completed successfully |
202 | Accepted | Request requires HITL approval (includes approval_id) |
400 | Client error | Invalid JSON, missing fields, provider mismatch |
401 | Authentication | Missing or invalid API key |
403 | Forbidden | Blocked by governance (PII, model allowlist, cost, content safety) |
404 | Not found | Resource not found |
410 | Gone | Model has been retired |
413 | Payload too large | Request body exceeds 10 MB |
429 | Rate limited | RPM limit exceeded or plan quota exhausted |
500 | Server error | Internal gateway error |
502 | Bad gateway | Failed to connect to upstream provider |
503 | Service unavailable | Circuit breaker open or gateway shutting down |
504 | Gateway timeout | Upstream provider timed out |
Complete error catalog
Authentication errors (401)
invalid_api_key
Missing or invalid Curate-Me API key.
{
"error": {
"message": "Missing or invalid credentials. Provide a valid gateway key via X-CM-API-Key / Authorization: Bearer <gateway-key>, or a valid dashboard access token via Authorization: Bearer <jwt>.",
"type": "authentication_error",
"param": null,
"code": "invalid_api_key"
}
}key_rotated
The API key has been rotated and the grace period has expired.
{
"error": {
"message": "API key has been rotated. Use the new key. Replacement key ID: key_xyz789",
"type": "authentication_error",
"param": null,
"code": "key_rotated"
}
}missing_provider_key
No provider API key was supplied and no stored secret exists.
{
"error": {
"message": "Missing provider API key. Provide your provider's API key via X-Provider-Key header, Authorization: Bearer <provider-key>, or store it via POST /gateway/admin/secrets.",
"type": "authentication_error",
"param": null,
"code": "missing_provider_key"
}
}Invalid request errors (400)
invalid_json
The request body is not valid JSON.
{
"error": {
"message": "Invalid JSON body",
"type": "invalid_request_error",
"param": null,
"code": "invalid_json"
}
}missing_model
The model field is missing from the request body.
{
"error": {
"message": "Missing 'model' field in request body",
"type": "invalid_request_error",
"param": null,
"code": "missing_model"
}
}unknown_model
The specified model is not recognized by the gateway.
{
"error": {
"message": "Unknown model 'foo-bar'. Supported prefixes: gpt-, o1-, o3-, claude-, gemini-, deepseek-",
"type": "invalid_request_error",
"param": null,
"code": "unknown_model"
}
}provider_mismatch
The model does not belong to the provider endpoint it was sent to.
{
"error": {
"message": "Model 'gpt-4o' is a openai model but was sent to the google endpoint. Use the correct endpoint.",
"type": "invalid_request_error",
"param": null,
"code": "provider_mismatch"
}
}request_too_large
The request body exceeds the 10 MB size limit.
{
"error": {
"message": "Request body too large. Maximum size is 10485760 bytes (10 MB).",
"type": "invalid_request_error",
"param": null,
"code": "request_too_large"
}
}model_retired
The requested model has been retired (past its shutdown date).
{
"error": {
"message": "Model 'gpt-4' has been retired (shutdown: 2026-01-15). Use 'gpt-4o' instead.",
"type": "invalid_request_error",
"param": null,
"code": "model_retired"
}
}Rate limit errors (429)
rate_limit
The organization has exceeded its requests-per-minute (RPM) limit.
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1709056860
Retry-After: 12{
"error": {
"message": "Rate limit exceeded. Retry after 12 seconds.",
"type": "rate_limit_error",
"param": null,
"code": "rate_limit"
}
}plan_limit_exceeded
The organization has exceeded its plan’s daily request quota or budget.
{
"error": {
"message": "Plan limit exceeded: free tier allows 100 requests per day",
"type": "insufficient_quota",
"param": null,
"code": "plan_limit_exceeded"
}
}Permission errors (403)
cost_limit
The estimated request cost exceeds the per-request cost cap.
{
"error": {
"message": "Estimated cost $3.50 exceeds per-request limit $2.00",
"type": "permission_error",
"param": null,
"code": "cost_limit"
}
}daily_budget
The organization’s daily budget has been exhausted.
{
"error": {
"message": "Daily budget exhausted: $24.50 spent + $0.52 estimated > $25.00 limit",
"type": "permission_error",
"param": null,
"code": "daily_budget"
}
}monthly_budget
The organization’s monthly budget has been exhausted.
{
"error": {
"message": "Monthly budget exhausted: $248.00 spent + $2.10 estimated > $250.00 limit",
"type": "permission_error",
"param": null,
"code": "monthly_budget"
}
}pii_detected
PII or secrets were detected in the request content.
{
"error": {
"message": "PII detected in request: credit card number found in message content",
"type": "permission_error",
"param": null,
"code": "pii_detected"
}
}model_not_allowed
The requested model is not in the organization’s allowed model list.
{
"error": {
"message": "Model 'gpt-4o' is not in the allowed model list for this organization",
"type": "permission_error",
"param": null,
"code": "model_not_allowed"
}
}needs_approval
The request requires human approval before execution.
{
"error": {
"message": "Request requires human approval: Estimated cost $12.50 exceeds HITL threshold $10.00",
"type": "permission_error",
"param": null,
"code": "needs_approval"
}
}Note: The OpenAI/Anthropic proxy endpoints return HTTP 202 with approval details instead of a 403 for HITL-triggered requests. The Google and DeepSeek proxies currently return 403.
HITL approval response (202)
When the HITL gate triggers, the OpenAI/Anthropic proxy returns a 202 with approval metadata:
HTTP/1.1 202 Accepted
X-CM-Approval-ID: apr_abc123def456
Retry-After: 30{
"status": "pending_approval",
"approval_id": "apr_abc123def456",
"retry_after_seconds": 30,
"message": "Request requires human approval: Estimated cost $12.50 exceeds HITL threshold $10.00",
"estimated_cost": 12.50,
"model": "gpt-4o"
}This is not an error per se — the request has been accepted and is awaiting approval. Poll GET /v1/approvals/{approval_id}/status to check the outcome.
Upstream errors (502, 504)
upstream_{status_code}
The upstream provider returned an error.
{
"error": {
"message": "Google Gemini API error: Invalid API key provided",
"type": "upstream_error",
"param": null,
"code": "upstream_401"
}
}timeout
The upstream provider timed out.
{
"error": {
"message": "Google Gemini API timed out",
"type": "timeout_error",
"param": null,
"code": "timeout"
}
}connection_error
Failed to establish a connection to the upstream provider.
{
"error": {
"message": "Failed to connect to Google Gemini API",
"type": "connection_error",
"param": null,
"code": "connection_error"
}
}circuit_breaker_open
The provider’s circuit breaker is open due to repeated failures.
{
"error": {
"message": "Google Gemini is temporarily unavailable (circuit breaker open)",
"type": "service_unavailable",
"param": null,
"code": "circuit_breaker_open"
}
}Internal errors (500)
internal_error
An unexpected error occurred within the gateway.
{
"error": {
"message": "Internal gateway error",
"type": "gateway_error",
"param": null,
"code": "internal_error"
}
}Retry guidance
| Error code | Retryable | Strategy |
|---|---|---|
rate_limit | Yes | Wait for Retry-After seconds, then retry |
plan_limit_exceeded | No | Upgrade plan or wait for the next billing period |
daily_budget | No | Wait until the next UTC day or increase the daily budget |
monthly_budget | No | Wait until the next month or increase the monthly budget |
cost_limit | No | Reduce max_tokens or use a cheaper model |
pii_detected | No | Remove PII from the request content |
model_not_allowed | No | Use an allowed model or update the allowlist |
needs_approval | Yes | Poll GET /v1/approvals/{id}/status and re-submit after approval |
circuit_breaker_open | Yes | Wait for retry_after_seconds and retry |
timeout | Yes | Retry with exponential backoff |
connection_error | Yes | Retry with exponential backoff |
upstream_429 | Yes | Wait for Retry-After from the provider |
upstream_500 | Yes | Retry with exponential backoff |
upstream_502 | Yes | Retry with exponential backoff |
upstream_503 | Yes | Retry with exponential backoff |
invalid_json | No | Fix the request body |
missing_model | No | Include the model field |
unknown_model | No | Use a supported model name |
provider_mismatch | No | Send the request to the correct provider endpoint |
invalid_api_key | No | Use a valid API key |
missing_provider_key | No | Include a provider API key |
internal_error | Yes | Retry with exponential backoff |
Retry headers
When the gateway retries an upstream request due to transient failures, it includes retry metadata in the response:
| Header | Description |
|---|---|
X-Gateway-Retry-Attempts | Number of retry attempts made |
X-Gateway-Retry-Delay-Ms | Total retry delay in milliseconds |
These headers are present on both successful and failed responses when retries occurred.