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. For stateless model requests, upstream HTTP errors are converted
to the OpenAI-compatible envelope, preserving their status and message.
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_inputs_unmappable | Agent invocations (model: "agent/<agent-id>"): version pinning (agent/<id>@<version>) is not available yet; or the agent’s declared inputs cannot be bound to a freeform input — it declares two or more named inputs, or a single non-text input (use POST /v1/agents/runs with named inputs 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, upstream_error | Model access is denied, or a stateless model request fails an upstream credit or department budget check. |
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. |
413 | — | — | JSON request body exceeds the 50 MB (52,428,800-byte) limit. Returned before route handling as {"message":"Request body too large. Maximum size is 50 MB."}. |
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.
Credit and budget refusals
Section titled “Credit and budget refusals”For stateless model requests (without store: true, conversation, or
previous_response_id), a credit or department budget check can return HTTP
403 before streaming starts, including when stream: true. The response
has error.type: "permission_error" and error.code: "upstream_error".
Inspect error.message for CHAT_DEPARTMENT_BUDGET_REACHED and its
explanation. CHAT_INSUFFICIENT_CREDITS identifies a credit refusal instead.
For model requests in a Kindo-managed conversation (store: true,
conversation, or previous_response_id), a credit or department budget
refusal during execution is recorded on the response. With stream: false,
the request returns HTTP 200 with status: "failed" and the recorded
CHAT_DEPARTMENT_BUDGET_REACHED or CHAT_INSUFFICIENT_CREDITS in
error.code. With streaming, a live error emits an error event with
code: "server_error" and the error message, then ends the stream. Do not
wait for a response.failed event on this path.
For model: "agent/<agent-id>", acceptance of the request starts an
asynchronous run. A refusal during execution can leave the response with
status: "failed". Poll GET /v1/responses/{id} and inspect the response
object’s error: error.code carries the recorded
CHAT_AGENT_BUDGET_REACHED, CHAT_DEPARTMENT_BUDGET_REACHED, or
CHAT_INSUFFICIENT_CREDITS when available, or server_error when no
specific error was recorded. With streaming, a live step can emit an
error event with code: "server_error" and the step’s error message,
followed by response.failed containing the final response object. The
HTTP status remains 200 once the stream has started.
Budgets and credits are separate checks: an agent or department budget can block a request while the organization still has credits. Do not retry a budget refusal while that budget still blocks the request. Ask your organization administrator to review it; see When a budget blocks a request.
Mid-stream errors
Section titled “Mid-stream errors”For stateless model requests, Kindo forwards upstream SSE events. If Kindo
cannot read the upstream stream after SSE has started, it emits an error
event followed by data: [DONE]:
event: errordata: {"error":{"message":"Stream processing error.","type":"server_error","code":"stream_error"}}
data: [DONE]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.
Upstream HTTP errors
Section titled “Upstream HTTP errors”For stateless model requests, an upstream 4xx or 5xx keeps its HTTP status and is
converted to the OpenAI-compatible envelope. error.code is
upstream_error; error.message carries the extracted upstream message
(or the upstream body as text when no message can be extracted).
For example, upstream 403 uses error.type: "permission_error".
Parse the HTTP status first and inspect the message for the refusal reason.
See also
Section titled “See also”- Authentication —
401causes. - Model catalog — model access and availability.
- Streaming — mid-stream error events.
- Response store pruning —
404causes.
