Skip to content

Commit 3106007

Browse files
authored
Merge pull request #125 from browser-use/overflow-error-timing
fix(opencode): publish overflow error when recovery is abandoned, not attempted
2 parents 7f37345 + f0752f0 commit 3106007

3 files changed

Lines changed: 70 additions & 1 deletion

File tree

‎packages/opencode/src/session/compaction.ts‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,13 +402,20 @@ const layer = Layer.effect(
402402
})
403403

404404
if (result === "compact") {
405+
// Recovery abandoned: this is where overflow becomes an outcome, so
406+
// the error event fires here rather than on the recoverable 413 in
407+
// processor.halt.
405408
processor.message.error = new SessionV1.ContextOverflowError({
406409
message: replay
407410
? "Conversation history too large to compact - exceeds model context limit"
408411
: "Session too large to compact - context exceeds model limit even after stripping media",
409412
}).toObject()
410413
processor.message.finish = "error"
411414
yield* session.updateMessage(processor.message)
415+
yield* events.publish(Session.Event.Error, {
416+
sessionID: input.sessionID,
417+
error: processor.message.error,
418+
})
412419
return "stop"
413420
}
414421

‎packages/opencode/src/session/processor.ts‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -638,8 +638,13 @@ const layer = Layer.effect(
638638
yield* status.set(ctx.sessionID, { type: "idle" })
639639
return
640640
}
641+
// Recovery attempt, not an outcome: auto-compaction will retry, so
642+
// nothing is published here. The durable message carries no error
643+
// either; announcing one on the error channel made every consumer
644+
// (CLI exit code, TUI toast, orchestrators) fail runs that recover.
645+
// If compaction cannot shrink the session, compaction.ts publishes
646+
// the terminal error.
641647
ctx.needsCompaction = true
642-
yield* events.publish(Session.Event.Error, { sessionID: ctx.sessionID, error })
643648
return
644649
}
645650
ctx.assistantMessage.error = error

‎packages/opencode/test/cli/run/run-process.test.ts‎

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,63 @@ describe("opencode run (non-interactive subprocess)", () => {
241241
60_000,
242242
)
243243

244+
cliIt.concurrent(
245+
"recovers from a provider size error via compaction without emitting an error event",
246+
({ llm, opencode }) =>
247+
Effect.gen(function* () {
248+
yield* llm.error(413, {
249+
error: { type: "request_too_large", message: "Request exceeds the maximum size" },
250+
})
251+
yield* llm.text("compacted history")
252+
yield* llm.text("recovered output")
253+
254+
const result = yield* opencode.run("recover after overflow", {
255+
format: "json",
256+
env: { OPENCODE_DISABLE_AUTOCOMPACT: "0" },
257+
})
258+
259+
opencode.expectExit(result, 0)
260+
const events = opencode.parseJsonEvents(result.stdout)
261+
expect(events.some((event) => event.type === "error")).toBe(false)
262+
expect(
263+
events.some(
264+
(event) =>
265+
event.type === "text" &&
266+
typeof event.part === "object" &&
267+
event.part !== null &&
268+
"text" in event.part &&
269+
event.part.text === "recovered output",
270+
),
271+
).toBe(true)
272+
}),
273+
60_000,
274+
)
275+
276+
cliIt.concurrent(
277+
"exits nonzero with an error event when compaction cannot shrink the session",
278+
({ llm, opencode }) =>
279+
Effect.gen(function* () {
280+
yield* llm.error(413, {
281+
error: { type: "request_too_large", message: "Request exceeds the maximum size" },
282+
})
283+
yield* llm.error(413, {
284+
error: { type: "request_too_large", message: "Request exceeds the maximum size" },
285+
})
286+
287+
const result = yield* opencode.run("overflow beyond recovery", {
288+
format: "json",
289+
env: { OPENCODE_DISABLE_AUTOCOMPACT: "0" },
290+
})
291+
292+
opencode.expectExit(result, 1)
293+
const events = opencode.parseJsonEvents(result.stdout)
294+
const errors = events.filter((event) => event.type === "error")
295+
expect(errors.length).toBe(1)
296+
expect(JSON.stringify(errors[0])).toContain("too large to compact")
297+
}),
298+
60_000,
299+
)
300+
244301
cliIt.concurrent(
245302
"rejects requested permissions by default and allows them with the dangerous flag",
246303
({ home, llm, opencode }) =>

0 commit comments

Comments
 (0)