Core API
Errors & rate limits
Parse gateway and upstream errors, decide when to retry, and collect a trace identifier.
On this page
This page is for developers diagnosing failed production requests or designing retry behavior.
Gateway-generated 401, 402, and 429 responses use a string in error. Upstream errors commonly use an OpenAI-compatible object. Clients must handle both.
{"error":"Unauthorized: Missing API key"}{"error":{"message":"The selected model rejected the request.","type":"invalid_request_error"}}Status codes#
| Status | Meaning | Retry? | Action |
|---|---|---|---|
| 400 | Invalid request, including unsupported masked image edits. | no | Fix the body or form fields. |
| 401 | Missing or unknown API key. | no | Fix server-side authentication. |
| 402 | Expired, disabled, parent-disabled, or depleted key. | no | Inspect key state and balance. |
| 403 | Upstream authorization or policy rejection. | usually no | Inspect the returned upstream body. |
| 404 | Unrecognized path prefix, or a model that cannot serve the requested endpoint. | no | Correct the endpoint. |
| 408 | Upstream timeout response. | before output only | Retry with bounded backoff if the operation is safe. |
| 413 | Upload too large, including image edits over the combined 8 MB limit. | no | Shrink or split the upload. |
| 429 | CLSSAI free daily pool exhaustion or an upstream limit. | later | Read the body and wait before retrying. |
| 502 | All gateway connection attempts failed. | yes | Retry with bounded backoff. |
| 503 | Gateway configuration or upstream availability failure. | yes | Retry later and report the trace if persistent. |
| 504 | Upstream gateway timeout. | yes | Retry before output with bounded backoff. |
CLSSAI does not impose a per-key RPM limit. Free users share a global daily pool; exhaustion returns the gateway 429 string below. Other 429 responses come from the upstream API and may use a different body or headers.
{"error":"Too Many Requests: Daily Free Quota Exhausted","message":"The global free tier limit for today has been reached. Please add funds."}Parse both shapes and retry safely#
const retryable = new Set([408, 429, 502, 503, 504]);
async function requestWithBackoff(url, init, attempts = 3) {
for (let attempt = 0; attempt < attempts; attempt += 1) {
const response = await fetch(url, init);
if (response.ok) return response;
const body = await response.json().catch(() => ({}));
const message = typeof body.error === "string"
? body.error
: body.error?.message ?? body.message ?? `HTTP ${response.status}`;
if (!retryable.has(response.status) || attempt === attempts - 1) throw new Error(message);
await new Promise((resolve) => setTimeout(resolve, 500 * (2 ** attempt)));
}
throw new Error("Request failed");
}Do not retry after an SSE stream has emitted its first event. The gateway itself makes at most two attempts for connection-level 502, 503, and 504 failures, except for request bodies too large to replay.
Trace a request#
Inference responses do not add an application-specific request ID. Record the cf-ray response header on every response, plus x-generation-id when an OpenAI-compatible response includes it. Share those identifiers, the timestamp, endpoint, and status with support; never share the API key.
Common mistakes#
- Do not assume
erroris always an object. - Do not infer that a path exists from a 401; authentication happens before route selection.
- Do not invent a per-key RPM threshold.
- Include
/v1in the OpenAI SDK base URL and omit it from the Anthropic SDK base URL. - Keep server calls out of the browser, preserve complete variant IDs, and check empty streaming
choicesarrays. - Record
cf-rayand, for OpenAI-compatible routes,x-generation-idwhen present.
Find answers to common questions or diagnose a failed request.
Frequently asked questions →Troubleshoot errors →