diff --git a/open-sse/utils/diagnostics.ts b/open-sse/utils/diagnostics.ts index 06f7a0a0b6..ebee72e1e8 100644 --- a/open-sse/utils/diagnostics.ts +++ b/open-sse/utils/diagnostics.ts @@ -323,8 +323,14 @@ export function describeMalformedNonStream( ): { message: string; code: string; type: string } { const body = resp && typeof resp === "object" ? (resp as Record) : null; if (body?.object === "response" && body.status === "failed") { + const err = body.error && typeof body.error === "object" ? (body.error as Record) : null; + const rawMessage = + typeof err?.message === "string" && err.message.trim().length > 0 ? err.message.trim() : null; return { - message: "upstream reported a failed response without usable output", + // Trim only here; buildErrorBody (chatCore) does the single sanitization pass. + message: rawMessage + ? `upstream reported a failed response: ${rawMessage}` + : "upstream reported a failed response without usable output", code: "upstream_response_failed", type: "upstream_response_error", }; diff --git a/tests/unit/diagnostics.test.ts b/tests/unit/diagnostics.test.ts index dbcb643480..62da56fc0c 100644 --- a/tests/unit/diagnostics.test.ts +++ b/tests/unit/diagnostics.test.ts @@ -105,6 +105,22 @@ test("failed Responses API body gets a request-scoped machine-readable classific }); }); +test("failed Responses API body surfaces the upstream error message when present", () => { + const failed = { + object: "response", + status: "failed", + output: [], + error: { code: "server_error", message: " Gemini 503: overloaded " }, + }; + const reason = detectMalformedNonStream(failed); + assert.equal(reason, "empty_choices"); + assert.deepEqual(describeMalformedNonStream(failed, reason), { + message: "upstream reported a failed response: Gemini 503: overloaded", + code: "upstream_response_failed", + type: "upstream_response_error", + }); +}); + test("detectMalformedNonStream returns 'empty_choices' when choice message has no content", () => { const body = { choices: [{ message: { content: "", tool_calls: null }, finish_reason: "stop" }],