Skip to content

Chat Completions API errors

POST /v1/chat/completions returns errors in OpenAI’s Chat Completions 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.

{
"error": {
"message": "Model 'unknown-model' not found.",
"type": "invalid_request_error",
"code": "model_not_found"
}
}
StatusTypeCommon codesCause
400invalid_request_errorinvalid_body, model_not_foundBody fails schema validation or references a missing model.
401——Missing/malformed/revoked key. Plain envelope: {"error": "Unauthorized"}.
403permission_errormodel_access_deniedModel access is denied.
403——An upstream credit or department budget check refuses the request.
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."}.
429rate_limit_error—Org or user rate limit. Honors Retry-After when present.
500server_errorinternal_errorUnexpected Kindo-side failure.
502server_errorupstream_empty_bodyUpstream returned an empty body.

Chat Completions does not emit 404 from Kindo’s edge — any 404 the client sees is upstream provider passthrough.

401 uses the plain-string envelope {"error": "Unauthorized"} rather than the typed {"error": {"message": "...", ...}} shape. This matches Kindo’s API-key middleware on /v1/chat/completions and /v1/responses.

A credit or budget check can reject the request with HTTP 403 before inference starts, including when stream: true. The LiteLLM error message contains CHAT_DEPARTMENT_BUDGET_REACHED followed by an explanation. This is a message identifier, not a guaranteed value of error.code; Kindo forwards the upstream error body.

CHAT_INSUFFICIENT_CREDITS means the credit check refused the request. A department budget can block a request even when the organization has credits. See When a budget blocks a request for scope and recovery. Do not retry a budget refusal while the budget still blocks the request; ask your organization administrator to review it.

When a DLP policy applies, every type: "file" content block is rejected with HTTP 400, regardless of its MIME type. The message is Binary document attachments cannot be DLP-redacted; request blocked (fail-closed). This is a policy refusal, not a provider file-format error. Send plain text as a type: "text" content block so Kindo can redact it, or ask your administrator about the applicable DLP policy. See Files and DLP for the request contract.

Once stream: true has flipped the response into SSE, errors arrive as an inline event: error SSE frame followed by data: [DONE]:

event: error
data: {"error":{"message":"upstream stream interrupted","type":"server_error","code":"stream_error"}}
data: [DONE]

Treat any event: error payload with code: "stream_error" as terminal. The outer HTTP status stays 200.

When LiteLLM or the upstream provider returns a 4xx or 5xx with its own body, Kindo forwards that body verbatim (preserving the upstream Content-Type) so 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.

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.