Skip to content

fix(opencode): converge overflow compaction instead of replaying the same message forever - #41

Merged
PierrotAWB merged 2 commits into
devfrom
andrew/repl-31509-overflow-replay
Sep 4, 2026
Merged

PierrotAWB merged 2 commits into
devfrom
andrew/repl-31509-overflow-replay

Conversation

@PierrotAWB

@PierrotAWB PierrotAWB commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

When a message is too large for the model, opencode compacts the conversation and re-sends the message. The retained window kept the original copy right next to the re-sent one, so the retry was exactly as large as the failure and the loop never ended. One production session repeated this 2,161 times over 12.8 hours. After this change the retry carries a single copy, and a turn that still overflows after one compaction stops with an error instead of compacting again.

Context

  • Postmortem: REPL-31509. A 614 KB .html attachment (96% one base64 image, ~580k tokens) was sent, stopped, and re-sent, so the context held two copies and Anthropic rejected it. Every compaction cycle then summarized the history before the message and appended a fresh copy of it, while filterCompacted still returned the original, so each retry was ~1.21M tokens.
  • Companion: andytown #26615 adds a coordinator-side breaker that aborts a session after three identical errors. That stops the bleeding; this PR fixes the mechanism so the loop cannot form.
  • Upstream anomalyco/opencode dev (a935432, 2026-09-03) has the same overflow replay code and the same filterCompacted, so this cannot be picked up by a base bump. Worth upstreaming after it bakes here.

Changes

Retained window on an overflow replay (session/compaction.ts). processCompaction computes tail_start_id from the history before the message it is about to replay, which always leaves that message inside the retained window. When a replay is emitted, the marker now retains nothing before itself, so the next model context is [marker, summary, replay]: one copy.

One overflow compaction per turn (session/prompt.ts). A message that still overflows after compaction replayed it can never fit. The second consecutive overflow ends the turn with ContextOverflowError on the assistant message instead of compacting again. A finished model step resets the counter.

Testing Done

  • bun test test/session/compaction.test.ts test/session/prompt.test.ts test/session/message-v2.test.ts: 150 pass.
  • New compaction test builds the incident shape (small turn, big message with a reply, the same big message re-sent, overflow marker) and asserts the post-compaction context is [marker, summary, replay] with the re-sent original gone. It fails on dev (two extra copies retained) and passes here.
  • New prompt-loop test drives a 413 → summary → 413 sequence through the real loop and asserts three provider hits, one compaction marker, and an assistant ending in ContextOverflowError / finish: "error".
  • bun run typecheck (tsgo) clean.

Rollout

Cut v1.17.14-11 from dev after merge, then bump OPENCODE_VERSION in apps/daytona-snapshot/Dockerfile and sandbox-packages/sandbox-upgrader/src/opencode-version.ts in andytown in one PR.

🤖 Generated with Claude Code


Summary by cubic

Fixes the overflow compaction loop that retried an oversized message forever, because the original copy was retained next to the replay. Now the retained window only keeps the replay, and a second consecutive overflow ends the turn with ContextOverflowError instead of compacting again. This addresses the runaway loop from REPL-31509.

  • In compaction.ts, the compaction marker now retains nothing before itself when replaying, so the next context is [marker, summary, replay].
  • In prompt.ts, the loop stops after one overflow compaction per turn and marks the assistant message as failed with ContextOverflowError.

Written for commit 3156f19. Summary will update on new commits.

Review in cubic

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@PierrotAWB

Copy link
Copy Markdown
Collaborator Author

CI note: unit (linux) fails on two @opencode-ai/core tests, Npm.add > reifies when package cache directory exists… and Npm.install > respects omit from project .npmrc, both 5 s timeouts against the npm registry. They fail the same way locally on origin/dev (ee04d03) right now, so this is registry latency, not this branch; typecheck, e2e (linux) and nix-eval are green and the session suites pass locally (150 tests). check-duplicates hit a TimeoutError in the inherited duplicate-PR checker; both jobs have been re-run.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 4 files

Re-trigger cubic

PierrotAWB and others added 2 commits September 4, 2026 09:40
An overflow compaction replays the overflowing user message but computed the
retained tail from the history before it, so filterCompacted kept the original
next to the replay and every retry was as large as the failure (REPL-31509:
2,161 identical cycles). The marker now retains nothing before itself when it
replays, so the next context is [marker, summary, replay].

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A message that still overflows after compaction replayed it can never fit; a
second consecutive overflow now ends the turn with ContextOverflowError instead
of compacting again.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@PierrotAWB
PierrotAWB force-pushed the andrew/repl-31509-overflow-replay branch from a8c53ff to 3156f19 Compare September 4, 2026 16:40
@PierrotAWB
PierrotAWB merged commit 1ae9b5c into dev Sep 4, 2026
12 checks passed
@PierrotAWB
PierrotAWB deleted the andrew/repl-31509-overflow-replay branch September 4, 2026 18:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant