Skip to content

fix(compaction): output-budget reservation capped at 20K for limit.input models, risking overflow #32656

Description

@hasitpbhatt

Description

In packages/opencode/src/session/overflow.ts:14-19, the usable() function reserves different output budgets depending on whether the model has limit.input set:

  • Without limit.input: usable = context - maxOutputTokens -- reserves the model's full output budget.
  • With limit.input: usable = limit.input - min(20K, maxOutputTokens) -- caps the reservation at 20K tokens, which is less than the model's actual max output (e.g. 32K for Claude/GPT-4o).

A model with limit.input = 200K and maxOutputTokens = 32K can grow 12K tokens past the safe compaction boundary before triggering, potentially overflowing the next API call's context window. The missing 12K of headroom means the session grows beyond what the model can actually accept on the next turn.

The COMPACTION_BUFFER cap was introduced as a partial fix, but the two code paths remain asymmetric:

// line 14-19
const reserved =
  input.cfg.compaction?.reserved ??
  Math.min(COMPACTION_BUFFER, ProviderTransform.maxOutputTokens(input.model, input.outputTokenMax))
return input.model.limit.input
  ? Math.max(0, input.model.limit.input - reserved)
  : Math.max(0, context - ProviderTransform.maxOutputTokens(input.model, input.outputTokenMax))

Fix: Remove the Math.min(COMPACTION_BUFFER, ...) wrapper so both paths reserve the full maxOutputTokens, then delete the unused COMPACTION_BUFFER = 20_000 constant.

- const reserved = input.cfg.compaction?.reserved ??
-   Math.min(COMPACTION_BUFFER, ProviderTransform.maxOutputTokens(input.model, input.outputTokenMax))
+ const reserved = input.cfg.compaction?.reserved ??
+   ProviderTransform.maxOutputTokens(input.model, input.outputTokenMax)

The test file at packages/opencode/test/session/compaction.test.ts already has three test cases labeled as known bugs (lines 469-535) that should pass after the fix. Related issues: #10634, #8089, #11086, #12621.

Plugins

n/a

OpenCode version

dev

Steps to reproduce

Set up a model with limit.input (e.g. Claude, Gemini), run a session until the context approaches the limit, and observe that compaction doesn't trigger early enough, causing the next API call to overflow.

Screenshot and/or share link

n/a

Operating System

n/a

Terminal

n/a

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions