Skip to content

Error Responses

Single reference for what clients see when ProxAI fails: payload fields, allowed type values, HTTP status semantics, and preserved upstream headers. For the internal projection pipeline, see Error Handling Internals.

{
"error": {
"message": "quota exhausted",
"type": "upstream_error",
"code": "rate_limit_exceeded",
"param": "input",
"status": 429
}
}

Rendered interactively:

{
    error:{
      message:"quota exhausted",
      type:"upstream_error",
      code:"rate_limit_exceeded",
      param:"input",
      status:429
    }
}
FieldTypeMeaning
messagestringHuman-readable error message
typeenumClient-facing error classification, snake_case
codestring?Upstream OpenAI-style error code, only when upstream provides one
paramvalue?Upstream OpenAI-style error param, only when upstream provides one
statusu16Numeric status carried inside the JSON/SSE payload
invalid_request_error
internal_error
upstream_request_error
upstream_error
upstream_response_body_read_error
upstream_error_body_empty
upstream_error_body_non_json
upstream_error_body_unknown_shape
stream_translation_error

ProxAI does not expose its internal typed error taxonomy verbatim. Each type above is a stable client-facing classification.

TypeTypical sourceHTTP statusDetails
invalid_request_errorInbound request parsing or validation400Client request did not match the detected protocol.
internal_errorConfig/runtime invariant/local IO/serialization500Internal details are projected into a stable client-facing error.
upstream_request_errorFailed to send request upstream502Provider request could not be sent or transport failed before a response status.
upstream_errorUpstream returned structured non-2xx errorUpstream statuscode and param are included only if upstream provided them.
upstream_response_body_read_errorFailed to read upstream error/success body502Body carrier failed while reading upstream response.
upstream_error_body_emptyUpstream non-2xx with empty bodyUpstream statusNo upstream code/param is fabricated.
upstream_error_body_non_jsonUpstream non-2xx body was not JSONUpstream statusMessage may include a compact body summary.
upstream_error_body_unknown_shapeUpstream non-2xx JSON had unknown shapeUpstream statusThe JSON was readable but not a supported error schema.
stream_translation_errorStreaming conversion or terminal-event failure502 or payload status in SSEUsed when a stream cannot be translated safely.

The [error_responses] config selects how this payload is rendered:

[error_responses]
format = "text" # or "json"
  • text: only payload.message is returned, as text/plain. Default for Zed readability.
  • json: the full wrapped JSON above is returned.
StatusMeaning
400Inbound request was invalid for the detected protocol (invalid_request_error)
500ProxAI runtime invariant, local IO, serialization, or internal body read failed (internal_error)
502 / 503 / 504Upstream send/status/body-read failure (upstream_*)
Upstream statusFor upstream non-2xx responses, ProxAI maps the upstream status into its client-facing status while keeping the upstream numeric status inside the payload

For streaming responses, the HTTP status has already started (usually 200) when the error occurs, so the error arrives as an SSE event carrying the numeric status field.

For upstream non-2xx responses, ProxAI preserves useful diagnostic headers when the upstream actually provides them:

  • Retry-After
  • upstream request id headers
  • rate-limit headers

It does not fabricate these headers. Response Content-Type is decided by the outbound protocol, not passed through from the upstream — see Contract C13. Upstream headers are filtered before forwarding — see Contract C14.

If an error happens after an SSE response has started, HTTP status can no longer be changed. ProxAI emits an SSE event: error payload with the same client-facing error object and a numeric status field.

event: error
data: {"type":"error","error":{"message":"stream error","type":"stream_translation_error","status":502}}
RuleReason
Do not expose internal typed error names verbatimClient-facing type values should remain stable and compact.
Do not fabricate upstream code or paramThey are only present when the upstream provided them.
Do not log request bodies, Authorization headers, or API keysError paths must remain privacy-safe.
Preserve useful upstream headers only when presentRetry-After, request ids, and rate-limit headers are diagnostic hints, not invented metadata.