fix: parse mid stream openai responses style errors to prevent infinite retries for errors that should STOP execution (#12768)

This commit is contained in:
Aiden Cline
2026-02-08 20:55:41 -06:00
committed by GitHub
parent 79879b43ce
commit 62f38087b8
2 changed files with 124 additions and 1 deletions

View File

@@ -796,7 +796,76 @@ export namespace MessageV2 {
case e instanceof Error:
return new NamedError.Unknown({ message: e.toString() }, { cause: e }).toObject()
default:
return new NamedError.Unknown({ message: JSON.stringify(e) }, { cause: e })
try {
const json = iife(() => {
if (typeof e === "string") {
try {
return JSON.parse(e)
} catch {
return undefined
}
}
if (typeof e === "object" && e !== null) {
return e
}
return undefined
})
if (json) {
const responseBody = JSON.stringify(json)
// Handle Responses API mid stream style errors
if (json?.type === "error") {
switch (json?.error?.code) {
case "context_length_exceeded":
return new MessageV2.APIError(
{
message: "Input exceeds context window of this model",
isRetryable: false,
responseBody,
},
{
cause: e,
},
).toObject()
case "insufficient_quota":
return new MessageV2.APIError(
{
message: "Quota exceeded. Check your plan and billing details.",
isRetryable: false,
responseBody,
},
{
cause: e,
},
).toObject()
case "usage_not_included":
return new MessageV2.APIError(
{
message:
"To use Codex with your ChatGPT plan, upgrade to Plus: https://chatgpt.com/explore/plus.",
isRetryable: false,
responseBody,
},
{
cause: e,
},
).toObject()
case "invalid_prompt":
return new MessageV2.APIError(
{
message: json?.error?.message || "Invalid prompt.",
isRetryable: false,
responseBody,
},
{
cause: e,
},
).toObject()
}
}
}
} catch {}
return new NamedError.Unknown({ message: JSON.stringify(e) }, { cause: e }).toObject()
}
}
}

View File

@@ -784,3 +784,57 @@ describe("session.message-v2.toModelMessage", () => {
])
})
})
describe("session.message-v2.fromError", () => {
test("serializes response error codes", () => {
const cases = [
{
code: "context_length_exceeded",
message: "Input exceeds context window of this model",
},
{
code: "insufficient_quota",
message: "Quota exceeded. Check your plan and billing details.",
},
{
code: "usage_not_included",
message: "To use Codex with your ChatGPT plan, upgrade to Plus: https://chatgpt.com/explore/plus.",
},
{
code: "invalid_prompt",
message: "Invalid prompt from test",
},
]
cases.forEach((item) => {
const input = {
type: "error",
error: {
code: item.code,
message: item.code === "invalid_prompt" ? item.message : undefined,
},
}
const result = MessageV2.fromError(input, { providerID: "test" })
expect(result).toStrictEqual({
name: "APIError",
data: {
message: item.message,
isRetryable: false,
responseBody: JSON.stringify(input),
},
})
})
})
test("serializes unknown inputs", () => {
const result = MessageV2.fromError(123, { providerID: "test" })
expect(result).toStrictEqual({
name: "UnknownError",
data: {
message: "123",
},
})
})
})