anomalyco / anomalyco/opencode
Failed compaction silently drops pre-tail history from the model context
@kitlangton is already working on this.
Since Aug 13, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Description
When a compaction summary turn fails with a provider error, everything before the compaction boundary is dropped from the model context and no summary replaces it. The messages stay in the database, so the UI looks fine — the model just stops knowing about the earlier turns, and it repeats on every following turn because the marker is already persisted.
Two things combine:
processCompactionpersiststail_start_idon the compaction part even when the summary turn failed. The early return only coversresult === "compact"(packages/opencode/src/session/compaction.ts:450-466); a provider error returns"stop"and falls straight through to the write.filterCompacteduses two different tests for "this compaction is complete". The truncation loop requiressummary && finish && !error(message-v2.ts:541-542), but the reordering branch below it only checkssummary(message-v2.ts:554-562). That branch returns[compaction..summary] + [tail..compaction] + [after summary], so everything beforetail_start_idis dropped. With a failed summary there is nothing to replace it, and the errored assistant message is itself dropped bytoModelMessagesEffect.
So the loop says "not complete, keep all history" while the reorder says "complete, drop everything before the tail". The result is neither the summary nor the history.
This is the specs/v2/session.md rule ("A failed or interrupted attempt therefore leaves the previous history boundary active") not holding in v1.
Not #30806 (dangling partial summary on abort, closed) or #24700 / #24781 (fork not remapping tail_start_id). #42063 is adjacent but complementary — it rejects empty summaries, and its guard is result === "continue" && !processor.message.error, so the errored path here never reaches it.
Disclosure: found and reproduced with AI assistance; I reviewed and verified every claim locally.
Plugins
No response
OpenCode version
dev @ cc4b456 (v1.18.18)
Steps to reproduce
Happens whenever the summary request fails in a non-retryable way — expired key, exhausted credits, model unavailable, content filter — which is likely exactly when the context is largest.
Reproduced end to end against the real SessionCompaction.process with persistence: three turns, then an auto-compaction whose summary request returns 401.
Before: process() returns stop, the summary message carries the API error with no finish, but tail_start_id is still written. The next turn sees 3 of 5 stored messages — the first two topics are gone.
After adding finish / !error to the reordering test, the next turn sees all 5.
Screenshot and/or share link
No response
Operating System
macOS 15
Terminal
No response
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.