Skip to content

Commit 73db0b0

Browse files
authored
fix: account for additional openai retry case (anomalyco#24063)
1 parent d9da4ae commit 73db0b0

3 files changed

Lines changed: 56 additions & 2 deletions

File tree

packages/opencode/src/provider/error.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,13 @@ export type ParsedStreamError =
111111
| {
112112
type: "api_error"
113113
message: string
114-
isRetryable: false
114+
isRetryable: boolean
115115
responseBody: string
116116
}
117117

118118
export function parseStreamError(input: unknown): ParsedStreamError | undefined {
119-
const body = json(input)
119+
const raw = json(input)
120+
const body = typeof raw?.message === "string" ? (json(raw.message) ?? raw) : raw
120121
if (!body) return
121122

122123
const responseBody = JSON.stringify(body)
@@ -150,6 +151,13 @@ export function parseStreamError(input: unknown): ParsedStreamError | undefined
150151
isRetryable: false,
151152
responseBody,
152153
}
154+
case "server_error":
155+
return {
156+
type: "api_error",
157+
message: typeof body?.error?.message === "string" ? body?.error?.message : "Server error.",
158+
isRetryable: true,
159+
responseBody,
160+
}
153161
}
154162
}
155163

packages/opencode/test/session/message-v2.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,6 +1075,30 @@ describe("session.message-v2.fromError", () => {
10751075
})
10761076
})
10771077

1078+
test("serializes OpenAI response server_error stream chunks as retryable APIError", () => {
1079+
const body = {
1080+
type: "error",
1081+
sequence_number: 2,
1082+
error: {
1083+
type: "server_error",
1084+
code: "server_error",
1085+
message:
1086+
"An error occurred while processing your request. You can retry your request, or contact us through our help center at help.openai.com if the error persists. Please include the request ID req_77eccd008d984bf6bf82d1b2c2b68715 in your message.",
1087+
param: null,
1088+
},
1089+
}
1090+
const result = MessageV2.fromError({ message: JSON.stringify(body) }, { providerID })
1091+
1092+
expect(result).toStrictEqual({
1093+
name: "APIError",
1094+
data: {
1095+
message: body.error.message,
1096+
isRetryable: true,
1097+
responseBody: JSON.stringify(body),
1098+
},
1099+
})
1100+
})
1101+
10781102
test("detects context overflow from APICallError provider messages", () => {
10791103
const cases = [
10801104
"prompt is too long: 213462 tokens > 200000 maximum",

packages/opencode/test/session/retry.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,4 +294,26 @@ describe("session.message-v2.fromError", () => {
294294
const result = MessageV2.fromError(error, { providerID: ProviderID.make("openai") }) as MessageV2.APIError
295295
expect(result.data.isRetryable).toBe(true)
296296
})
297+
298+
test("converts OpenAI server_error stream chunks to retryable APIError", () => {
299+
const result = MessageV2.fromError(
300+
{
301+
message: JSON.stringify({
302+
type: "error",
303+
sequence_number: 2,
304+
error: {
305+
type: "server_error",
306+
code: "server_error",
307+
message: "An error occurred while processing your request.",
308+
param: null,
309+
},
310+
}),
311+
},
312+
{ providerID: ProviderID.make("openai") },
313+
)
314+
315+
expect(MessageV2.APIError.isInstance(result)).toBe(true)
316+
expect((result as MessageV2.APIError).data.isRetryable).toBe(true)
317+
expect(SessionRetry.retryable(result)).toBe("An error occurred while processing your request.")
318+
})
297319
})

0 commit comments

Comments
 (0)