Compare commits

...

2 Commits

Author SHA1 Message Date
opencode-agent[bot] 8378856a90 refactor(console): simplify provider error parsing 2026-06-02 13:54:04 +00:00
opencode-agent[bot] 1e1dc56a09 fix(console): parse provider SSE error bodies 2026-06-02 12:48:31 +00:00
3 changed files with 61 additions and 1 deletions
@@ -48,6 +48,7 @@ import { localeFromRequest } from "~/lib/language"
import { createModelTpmLimiter } from "./modelTpmLimiter"
import { createModelTpsLimiter } from "./modelTpsLimiter"
import { accumulateUsage, HOT_WORKSPACES } from "./usageBatcher"
import { parseProviderErrorBody } from "./providerError"
type ZenData = Awaited<ReturnType<typeof ZenData.list>>
type RetryOptions = {
@@ -248,7 +249,15 @@ export async function handler(
// Handle non-streaming response
if (!isStream || [400, 404, 429].includes(res.status)) {
const json = await res.json()
const json = await (async () => {
if (res.status === 200) return res.json()
const body = await res.text()
try {
const parsed = JSON.parse(body)
if (parsed && typeof parsed === "object") return parsed as Record<string, any>
} catch {}
return parseProviderErrorBody(body, res.statusText)
})()
await rateLimiter?.track()
const usage = providerInfo.extractUsage(json)
if (usage) {
@@ -0,0 +1,25 @@
export function parseProviderErrorBody(body: string, statusText: string) {
const text = body.trim()
const sseData = text
.split(/\r?\n/)
.map((line) => line.trim())
.filter((line) => line.startsWith("data:"))
.map((line) => line.slice(5).trim())
.filter((line) => line && line !== "[DONE]")
const parsed = (() => {
for (const data of sseData) {
try {
const json = JSON.parse(data)
if (json && typeof json === "object") return json as Record<string, any>
} catch {}
}
})()
if (parsed) return parsed as Record<string, any>
return {
error: {
message: sseData[0] || text || statusText,
},
}
}
@@ -0,0 +1,26 @@
import { describe, expect, test } from "bun:test"
import { parseProviderErrorBody } from "../src/routes/zen/util/providerError"
describe("provider error parsing", () => {
test("parses SSE error bodies from upstream rate limits", () => {
expect(
parseProviderErrorBody(
'event:error\ndata: {"error":{"type":"rate_limit_error","message":"Too many requests"}}\n\n',
"Too Many Requests",
),
).toEqual({
error: {
type: "rate_limit_error",
message: "Too many requests",
},
})
})
test("wraps plain text errors in provider error shape", () => {
expect(parseProviderErrorBody("overloaded", "Too Many Requests")).toEqual({
error: {
message: "overloaded",
},
})
})
})