Repository navigation
Description
Description
OpenCode V2 auto-compaction does not trigger for long Fable sessions that exceed the Zen/Fable request byte envelope before they approach the advertised token context limit.
Observed behavior:
- Model:
opencode/claude-fable-5#highthrough Zen. - Catalog limit for Fable:
context=1000000,output=128000. - V2 auto-compaction threshold:
context - max(output, buffer)=872000estimated tokens. - A real long session translated to
646LLM messages and about1.31 MBof request JSON before system/tools. Token.estimate(JSON.stringify({ system, messages, tools }))for messages-only shape was about328000, below the872000threshold, soSessionCompaction.compactIfNeededreturned false.- The provider then failed before any assistant output with HTTP 400:
Provider request failed with HTTP 400: {"type":"error","error":{"type":"invalid_request_error","message":"Error from provider (Console): Upstream request failed"}}
No session.next.compaction.* events were emitted. The turn became session.next.step.failed.2.
Why This Happens
The proactive path in packages/core/src/session/compaction.ts only checks estimated tokens against the advertised model context:
estimate({ system: input.request.system, messages: input.request.messages, tools: input.request.tools }) <=
context - Math.max(output, config.buffer)The reactive overflow path in packages/core/src/session/runner/llm.ts only recovers when isContextOverflowFailure(...) is true. The Zen/Fable response body says only Upstream request failed, so packages/llm/src/provider-error.ts does not classify it as context overflow.
Synthetic Reproduction
Against https://opencode.ai/zen/v1/messages with model=claude-fable-5, max_tokens=1, and no private content:
700000characters in one user text message succeeds.1000000characters in one user text message returns the same generic HTTP 400Upstream request failed.650tiny alternating messages ending in a user turn succeeds, so this is not simply message count.- Small Anthropic tool-use/tool-result shapes also succeed, so this is not obviously invalid tool-result ordering.
Expected Behavior
V2 should compact before sending requests that are too large for the route/provider envelope, or classify this generic Zen/Fable 400 as recoverable overflow when it happens before assistant output.
Possible fixes:
- Add a byte-envelope guard to
SessionCompaction.compactIfNeeded, perhaps route/model configurable and separate from token context. - Add provider/route metadata for max request bytes or a lower effective compaction threshold for Zen/Fable.
- Improve Zen/Fable error classification so this generic request-size failure becomes
context-overflowwhen appropriate.
Related Issues
Related but not the same:
- Sub-agents hang indefinitely on context overflow — no compaction triggered #25187: sub-agent context overflow and incomplete overflow classification.
- [Network connection lost] due to Context overflow at model limit misclassified — no compaction, no retry, session dies!! #33376: context overflow misclassified through an unrelated error path.
- fix(compaction): output-budget reservation capped at 20K for limit.input models, risking overflow #32656: output-budget reservation issue in the older compaction path.
This report is specifically about V2 packages/core/src/session/compaction.ts using token context only while Zen/Fable appears to fail at a smaller request-byte envelope.
Activity
opencode-agent commentedon Jul 8, 2026
Active proposed fix: #35687 currently targets
dev; confirm V2 landing/port plan.opencode-agent commentedon Jul 10, 2026
Audit: #35671 and #36163 improve overflow classification and compaction recovery, but this issue is specifically about request-byte-envelope failures occurring before token-threshold auto-compaction. Keeping open until the request-size trigger itself is addressed or verified fixed.
opencode-agent commentedon Jul 10, 2026
Additional audit context: this remains open correctly. PR #36163 improves resilient compaction, but PR #35687 explicitly targets the request-byte-envelope compaction case and is still open/against
dev.kitlangton commentedon Jul 13, 2026
Confirmed with another V2 reproduction, this time through an OpenAI-compatible route returning an explicit HTTP 413:
request_body_too_large, and every continuation retried the same oversized history.PR #36589 addresses both failure modes: it triggers compaction at 8 MiB independently of token pressure, then rolls large histories through bounded compaction requests instead of sending the entire old history in one request. The previously wedged session completed compaction and resumed successfully with that change deployed.