From b697a6aaecd5d56e74d78980c2d952715a6ecfe4 Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 10 Sep 2026 15:06:24 -0700 Subject: [PATCH] fix(opencode): classify OpenRouter's typeless 502 overflow chunk as ContextOverflowError OpenRouter relays an upstream context-window overflow mid-stream as { code: 502, message, metadata } with no type field, so parseStreamError returned undefined and the turn died as an opaque UnknownError instead of triggering compaction. Match the message text with the shared overflow patterns before the type gate. USE-2673. Co-Authored-By: Claude Fable 5.1 --- packages/opencode/src/provider/error.ts | 18 ++++++++++++------ .../opencode/test/session/message-v2.test.ts | 17 +++++++++++++++++ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/packages/opencode/src/provider/error.ts b/packages/opencode/src/provider/error.ts index 21149a2cf389..b13a3375a483 100644 --- a/packages/opencode/src/provider/error.ts +++ b/packages/opencode/src/provider/error.ts @@ -99,21 +99,27 @@ export type ParsedStreamError = responseBody: string } +// OpenRouter relays upstream overflow as a typeless `{ code: 502, message }` chunk. +function isOverflow(body: { error?: { code?: string; message?: string }; message?: string }) { + return body.error?.code === "context_length_exceeded" || isContextOverflow(body.error?.message ?? body.message ?? "") +} + export function parseStreamError(input: unknown): ParsedStreamError | undefined { const raw = json(input) const body = typeof raw?.message === "string" ? (json(raw.message) ?? raw) : raw if (!body) return const responseBody = JSON.stringify(body) + if (isOverflow(body)) { + return { + type: "context_overflow", + message: "Input exceeds context window of this model", + responseBody, + } + } if (body.type !== "error") return switch (body?.error?.code) { - case "context_length_exceeded": - return { - type: "context_overflow", - message: "Input exceeds context window of this model", - responseBody, - } case "insufficient_quota": return { type: "api_error", diff --git a/packages/opencode/test/session/message-v2.test.ts b/packages/opencode/test/session/message-v2.test.ts index 1de84c9dd95b..4dbddcc09b43 100644 --- a/packages/opencode/test/session/message-v2.test.ts +++ b/packages/opencode/test/session/message-v2.test.ts @@ -1382,6 +1382,23 @@ describe("session.message-v2.fromError", () => { }) }) + test("serializes OpenRouter typeless overflow chunks as ContextOverflowError", () => { + const input = { + code: 502, + message: "Your input exceeds the context window of this model. Please adjust your input and try again.", + metadata: { error_type: "provider_unavailable" }, + } + const result = MessageV2.fromError(input, { providerID }) + + expect(result).toStrictEqual({ + name: "ContextOverflowError", + data: { + message: "Input exceeds context window of this model", + responseBody: JSON.stringify(input), + }, + }) + }) + test("serializes response error codes", () => { const cases = [ {