Skip to content

bug(v2): Fable/Zen request-size 400 bypasses auto-compaction #35013

Closed

Description

@kitlangton

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#high through Zen.
  • Catalog limit for Fable: context=1000000, output=128000.
  • V2 auto-compaction threshold: context - max(output, buffer) = 872000 estimated tokens.
  • A real long session translated to 646 LLM messages and about 1.31 MB of request JSON before system/tools.
  • Token.estimate(JSON.stringify({ system, messages, tools })) for messages-only shape was about 328000, below the 872000 threshold, so SessionCompaction.compactIfNeeded returned 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:

  • 700000 characters in one user text message succeeds.
  • 1000000 characters in one user text message returns the same generic HTTP 400 Upstream request failed.
  • 650 tiny 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-overflow when appropriate.

Related Issues

Related but not the same:

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

  1. added
    coreAnything pertaining to core functionality of the application (opencode server stuff)
    bugSomething isn't working
    on Jul 5, 2026
  2. opencode-agent commented on Jul 8, 2026

    @opencode-agent
    Contributor

    Active proposed fix: #35687 currently targets dev; confirm V2 landing/port plan.

  3. opencode-agent commented on Jul 10, 2026

    @opencode-agent
    Contributor

    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.

  4. opencode-agent commented on Jul 10, 2026

    @opencode-agent
    Contributor

    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.

  5. kitlangton commented on Jul 13, 2026

    @kitlangton
    ContributorAuthor

    Confirmed with another V2 reproduction, this time through an OpenAI-compatible route returning an explicit HTTP 413:

    • The model advertised an approximately 1M-token context.
    • The session was around 240k input tokens, so token-based auto-compaction did not run.
    • The serialized inference request exceeded the service's independent 10 MiB body limit.
    • The request failed with 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    2.0bugSomething isn't workingcoreAnything pertaining to core functionality of the application (opencode server stuff)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions