Platform
Errors
Status codes, error codes, and which errors to retry.
Error shape
Errors return an HTTP status and a JSON body with an error object. Use code to decide what to do; the message is for people.
402 response
{
"error": {
"message": "Insufficient balance ($0.00). Add funds to continue.",
"type": "insufficient_balance",
"code": "insufficient_balance"
}
}This shape is used on every route. The one exception is an unknown model on the Messages route, which answers in Anthropic's shape: type: "error" with a nested error object.
Status and error codes
| Status | Code | Meaning | What to do |
|---|---|---|---|
| 400 | invalid_json | The body is not a valid JSON object. | Fix the request body. |
| 400 | model_not_found | The model name is not recognized. | Use kael-beta. |
| 400 | param: reasoning_effort | The thinking level is not off, low, high, max, z-low, or z-high. | See Thinking levels. |
| 400 | invalid_request | The request was rejected as invalid. | Check your messages, tools and parameters. |
| 400 | context_length_exceeded | The request is too long for the context window. | Shorten the messages, tools or attachments. |
| 401 | missing_api_key | No API key was sent. | Send a key in a supported header. |
| 401 | invalid_api_key | The key is unknown or revoked. | Create a new key. |
| 402 | insufficient_balance | Your balance is $0 or below. | Add credit, then retry. |
| 413 | request_too_large | The request is too large. | Send less data. |
| 429 | rate_limit_exceeded | Too many requests in a minute, or Kael is briefly busy. | Back off, then retry. |
| 429 | concurrency_limit_exceeded | Too many requests running at once. | Wait for one to finish. |
| 500 | billing_unavailable | Your balance could not be checked. | Retry shortly. |
| 502 | upstream_unreachable | Kael could not complete the request. | Retry. |
| 502 | upstream_error | Kael could not complete the request. | Retry. |
| 503 | upstream_unavailable | Kael is temporarily unavailable. | Retry shortly, with backoff. |
| 504 | upstream_timeout | The request took too long. | Retry, or lower the thinking level or split the task. |
What to retry
- Retry
429,500,502,503and504, with exponential backoff and a little random jitter. - Do not retry
400,401,402or413until you have fixed the cause. The same request will fail the same way. - A retry is a new request, billed like any other if it succeeds.
Python
import random
import time
RETRY = {429, 500, 502, 503, 504}
def with_retries(send, attempts=5):
for attempt in range(attempts):
response = send()
if response.status_code not in RETRY:
return response
time.sleep(min(30, 2 ** attempt) + random.random()) # backoff with jitter
return responseErrors in a stream
An error before streaming starts uses a normal status code. An error after it starts arrives as an event inside the stream, because the status is already 200. See Streaming.