Messages API errors
POST /v1/messages returns errors using Anthropic’s standard error
envelope. Errors that originate at Kindo’s edge use the table below;
errors that originate upstream are forwarded verbatim with the
upstream body and content-type.
Envelope
{ "type": "error", "error": { "type": "invalid_request_error", "message": "max_tokens is required" }}Status / type / code reference
| Status | Type | Common codes | Cause |
|---|---|---|---|
400 | invalid_request_error | — | Body fails schema validation (missing max_tokens, malformed messages, etc.) or references a missing model. |
401 | authentication_error | — | Missing, malformed, or revoked API key. |
403 | permission_error | — | The key authenticated, but the user group does not grant access. |
429 | rate_limit_error | — | Org or user rate limit. Honors Retry-After when present. |
500 | api_error | — | Unexpected Kindo-side failure. |
502 | upstream_empty_body | — | Upstream returned an empty body. Example: {"type":"error","error":{"type":"upstream_empty_body","message":"..."}} |
401 note
On /v1/messages, 401 returns Anthropic’s typed authentication_error envelope rather than the plain-string {"error":"Unauthorized"} shape used on /v1/chat/completions and /v1/responses.
{ "type": "error", "error": { "type": "authentication_error", "message": "Unauthorized" }}The Messages API uses Anthropic’s typed envelope, which includes type but not a separate code field. (This differs from the Chat Completions and Responses APIs, where errors include both type and code.)
Mid-stream errors
If stream: true has flipped the response into SSE, errors arrive
as an event: error frame before the stream terminates:
event: errordata: {"type":"error","error":{"type":"overloaded_error","message":"upstream overloaded"}}The outer HTTP status stays 200 because headers were already
flushed when streaming began. SDK consumers should treat any
mid-stream error event as terminal.
Provider passthrough
When an upstream provider (Anthropic, etc.) returns a 4xx or 5xx
with its own body, Kindo forwards that body verbatim, preserving the
upstream Content-Type. Your client sees whatever shape the
upstream produced. The exception is
upstream_empty_body, which Kindo emits (as the value of error.type) when the upstream returned
an HTTP error with no body so consumers always have a parseable JSON
envelope.
If you want a single consistent error shape across providers, parse on the outer HTTP status first; only fall back to body inspection when you need provider-specific detail.
See also
- Authentication —
401causes. - Model catalog —
403causes. - Streaming — mid-stream error events.