Skip to content

core: v2 compaction injects max_output_tokens and leaves oversized sessions unrecoverable #36253

Closed

Description

@kitlangton

Summary

V2 compaction forces generation.maxTokens, which OpenAI Responses serializes as max_output_tokens, even when the ordinary session request leaves that option unset. If the endpoint rejects that parameter, compaction fails and the runner immediately sends the original oversized request, leaving the session stuck on context_length_exceeded.

Environment

  • opencode version: TUI 0.0.0-next-15234; elected server 0.0.0-next-15258 at the time of failure. The same source path remains on current origin/v2 and 0.0.0-next-15277.
  • OS: macOS 25.5.0 (arm64)
  • Terminal: WarpTerminal, TERM=xterm-256color, COLORTERM=truecolor
  • Shell: /bin/zsh
  • Install/channel: global next installation using the V2 managed service
  • Active plugins: share-with-team.ts, debug-workspace-plugin.ts, @warp-dot-dev/opencode-warp

Reproduction

  1. Configure a V2 model through @ai-sdk/openai / OpenAI Responses whose endpoint accepts ordinary requests but rejects max_output_tokens.
  2. Continue a session until V2's predictive context estimate triggers automatic compaction.
  3. Submit another prompt, or request manual compaction.
  4. Observe that the compaction request fails with Unsupported parameter: max_output_tokens.
  5. Observe that automatic compaction returns false, after which the runner sends the original uncompressed request and receives context_length_exceeded.

Expected Behavior

Compaction should not add a request parameter that is absent from the ordinary request and unsupported by the selected endpoint. A failed predictive compaction should also avoid leaving the session in a repeated compaction-failure/context-overflow loop.

Actual Behavior

The durable event sequence was:

session.compaction.started (reason=auto)
session.compaction.failed  Provider request failed with HTTP 400: {"detail":"Unsupported parameter: max_output_tokens"}
session.step.started
session.step.failed        context_length_exceeded: Your input exceeds the context window of this model.
session.execution.failed

Manual compaction failed with the same unsupported parameter:

session.compaction.started (reason=manual)
session.compaction.failed  Provider request failed with HTTP 400: {"detail":"Unsupported parameter: max_output_tokens"}

Additional Context

The source path on origin/v2 at d54038b9d20f8df7955ffd3ae4e99bce31b50aaf is deterministic:

  1. packages/core/src/session/runner/model.ts:202-207 selects OpenAIResponses.route for aisdk:@ai-sdk/openai models.
  2. packages/core/src/session/compaction.ts:207-225 caps the summary at 4096 tokens and explicitly sets generation: { maxTokens: summaryOutput }.
  3. packages/llm/src/protocols/openai-responses.ts:482-495 lowers generation.maxTokens to max_output_tokens.
  4. packages/core/src/session/runner/llm.ts:213-218 only restarts after compaction when compactIfNeeded(...) returns true.
  5. When compaction returns false, execution falls through to llm.stream(hookedRequest) at packages/core/src/session/runner/llm.ts:236, sending the original oversized request.

The ordinary request does not set generation.maxTokens, so this parameter is introduced specifically by compaction. This explains why the compaction request fails on the unsupported parameter while the following ordinary request instead reaches the endpoint's context-window validation.

Related: #27547 reported max_output_tokens rejection through a third-party Codex auth plugin and was closed as non-actionable in stock V1. This report is the stock V2 compaction request construction and does not depend on that plugin path.

The affected session contains private project data, so only sanitized event types and provider errors are included.

Activity

  1. rasitakyol commented on Jul 16, 2026

    @rasitakyol

    I confirmed this on current dev (c69abee): compaction still supplies generation.maxTokens even when the ordinary request omits it, and a failed predictive compaction can fall through to the original oversized request. I can take a focused, regression-tested fix split into (1) avoid introducing a provider parameter absent from the ordinary request and (2) prevent the oversized fall-through after failed predictive compaction. Is that behavior split acceptable, and should the second case persist the compaction failure as the terminal error?

  2. opencode-agent commented on Aug 3, 2026

    @opencode-agent
    Contributor

    Fixed on v2 by #36267: compaction no longer injects generation.maxTokens / max_output_tokens, and failed automatic compaction now stops rather than sending the original oversized request.

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions