Responses API errors
POST /v1/responses returns errors in OpenAI’s Responses 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
Section titled “Envelope”{ "error": { "message": "Model 'unknown-model' not found.", "type": "invalid_request_error", "code": "model_not_found" }}Status / type / code reference
Section titled “Status / type / code reference”| Status | Type | Common codes | Cause |
|---|---|---|---|
400 | invalid_request_error | invalid_body, model_not_found, unsupported_parameter, unsupported_tool_type, mutually_exclusive_parameters | Body fails schema validation, references a missing model, asks for a feature not yet implemented (e.g. background: true on a Kindo-managed conversation), includes an mcp tool on a stateless request (set store: true or pass conversation), or sets both previous_response_id and conversation. |
400 | invalid_request_error | agent_version_pinning_unsupported, agent_not_invocable, agent_inputs_unmappable | Agent invocations (model: "agent/<agent-id>"): version pinning (agent/<id>@<version>) is not available yet; the agent is trigger-driven and cannot be invoked directly; or the agent declares two or more named inputs (use POST /v1/agents/runs instead). model_not_found also covers unknown and inaccessible agent IDs — indistinguishable from an unknown model. See the agent invocation guide. |
401 | — | — | Missing, malformed, or revoked API key. The body is a plain string envelope: {"error": "Unauthorized"}. |
403 | permission_error | model_access_denied | The key authenticated, but the user group does not grant access to the model. |
404 | not_found | — | E.g. GET /v1/responses/{id} for a response that does not exist or has been pruned. |
404 | invalid_request_error | previous_response_not_found | previous_response_id references a response that is unknown, inaccessible, or was not stored (stateless responses cannot be chained). Matches OpenAI’s wire shape for this error. |
429 | rate_limit_error | — | Org or user rate limit exceeded. Honors the Retry-After header when present. |
500 | server_error | internal_error | Unexpected Kindo-side failure. |
502 | server_error | upstream_empty_body | Upstream LiteLLM / provider returned an empty response. |
401 exception
Section titled “401 exception”The 401 envelope is the plain-string form
{"error": "Unauthorized"} rather than the typed
{"error": {"message": "...", "type": "...", "code": "..."}} shape.
This matches how Kindo’s API-key middleware reports auth failures
across the Chat Completions and Responses APIs.
Mid-stream errors
Section titled “Mid-stream errors”If stream: true is set and an error occurs after the SSE has
started, Kindo emits an error event followed by response.failed:
event: errordata: {"error":{"message":"upstream stream interrupted","type":"server_error","code":"stream_error"}}
event: response.faileddata: {"id":"resp_abc123","status":"failed","object":"response"}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.
See Streaming for the full SSE protocol.
Provider passthrough
Section titled “Provider passthrough”When an upstream provider (Anthropic, OpenAI, 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 — Kindo does not rewrap. The exception is
upstream_empty_body, which Kindo emits when the upstream returned
an HTTP error with no body so consumers always have a parseable JSON
envelope to log.
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
Section titled “See also”- Authentication —
401causes. - Model catalog —
403causes. - Streaming — mid-stream error events.
- Response store pruning —
404causes.