fix(translation): return HTTP 502 when Responses generation fails - #703
Conversation
…tus failed Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (5)
Included review availability: Your plan provides up to 12 included reviews per hour; 10 remain after this review. WalkthroughThe translation layer now rejects failed Responses payloads as upstream failures. The client maps these failures to HTTP 502 responses while preserving provider error details. Tests cover translation targets and client integration behavior. ChangesFailed Responses handling
Priority: ➖ Normal Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: ⚪ Minimal · up to The failed-response handling change has no identified merge-blocking risk. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
A rabbit found a failed reply Comment |
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
Signed-off-by: Elyas Mehtabuddin <emehtabuddin@nvidia.com>
{ "id": "resp_failed", "object": "response", "model": "failed", "status": "failed", "error": { "code": "server_error", "message": "deterministic upstream failure" }, "output": [], "usage": null }Request flow
An application sends a request to Switchyard. Switchyard forwards it to a model provider using the OpenAI Responses API, then returns the answer in the format the application requested: Chat Completions, Anthropic Messages, or Responses.
This PR covers a non-streaming response: the provider sends one JSON document with the generation status, output, and token usage. Switchyard reads the whole document before converting it; the code calls this a buffered response. A streaming response sends events as the model generates its answer and uses separate handling.
Problem
The JSON above is a response from the model provider to Switchyard. The provider sends HTTP 200, but the document says
status: "failed"and contains no generated answer (output: []). HTTP 200 alone does not mean that generation succeeded.Switchyard converts this failed response into an empty successful answer for applications using Chat Completions or Anthropic Messages. Applications using Responses receive
status: "failed"in the JSON but still get HTTP 200. Switchyard also counts the failed model call as a success and does not try another model.The result is an application receiving an empty answer without an HTTP error:
Fix
OpenAiResponsesCodec::decode_responsenow checks the provider's generation status before converting the answer. It treatsstatus: "failed"as a provider failure, which the HTTP client reports as HTTP 502 (Bad Gateway).Switchyard counts the failed model call as an error and tries another model when the route supports fallback. If this failure reaches the application, Switchyard returns HTTP 502 on Chat Completions, Anthropic Messages, and Responses.
Applications using an OpenAI API receive the provider's message and nonempty string error code. Applications using Anthropic Messages receive
type: "api_error"and the provider's message. The shared HTTP error mapper also preserves codes from ordinary upstream HTTP errors and usesupstream_errorwhen the code is missing, empty, or not a string.The HTTP client uses
redact_forwarded_headersto remove echoed caller credentials before returning or logging the error. Afailedstatus still counts as a provider failure when the error details are missing or malformed.Verification
The local provider returns the JSON above. Switchyard uses this configuration:
Every response includes
message: "deterministic upstream failure". The same three requests with a completed provider response return HTTP 200 andPONG, with 12 input tokens and 6 output tokens each.Requests to a real Responses provider using
openai/openai/gpt-5.6-solalso return HTTP 200 andPONGthrough all three endpoints, with 12 input tokens and 6 output tokens each./v1/statsreports nine requests and three errors across the failed, completed, and real-provider cases.Compatibility: When this failure reaches an application using Responses, the application now receives HTTP 502 instead of an HTTP-200 body with
status: "failed". Successful and incomplete Responses keep their existing behavior.Tests
The HTTP tests check failed Responses, error counts, and fallback on all three public APIs. Chat Completions tests also cover missing or malformed error details, invalid or empty codes, and credential redaction. Translation tests check
UpstreamFailurewith the provider's message and retain coverage for incomplete responses.