Skip to content

[Bug] In-flight prune is a no-op (postTokens == prePruneTokens) at 229k tokens → request exceeds server context → empty-response resume loop #346

Description

@ranxianglei

Mechanism (proven from plugin daily logs)

Two production sessions (headless opencode, resumed per-message by an orchestrator) grew until every request failed. The plugin's own log shows the root cause:

2026-08-27T15:59:26Z Chat transform complete | session=ses_7fb333d7… messages=145 prePruneTokens=229479 postTokens=229479 nudged=false
2026-08-28T14:28:31Z Chat transform complete | session=ses_7fb2e8b9… messages=99  prePruneTokens=229535 postTokens=229535 nudged=false

postTokens == prePruneTokens on every transform — even at 229k tokens. The in-flight prune never removes anything, nudged=false throughout, and the persisted state shows lastCompaction: 0 (proactive compaction also never fired; stats.totalPruneTokens 37k/230k respectively, all content parked in prune.messages).

Failure chain

  1. Conversation reaches ~229k tokens (plus ~15-20k system+tool schema + max_tokens: 16384)
  2. Total exceeds the serving backend's context window (sglang qwen 27B, max_model_len: 262144) → immediate request rejection
  3. opencode run ends with exit 0 and zero output (no error surfaced)
  4. Orchestrator retries → identical ~4.6s failure, forever (3× consecutive observed per session)

Both sessions froze at almost exactly the same size (229,479 / 229,535) — the length-rejection wall.

Environment

  • opencode 1.14.46 + opencode-acp@latest (plugin log says v=1.14.25), direct-to-sglang (no bili in this path)
  • Headless per-message spawn+resume (ACP path), daemon-driven
  • acp.jsonc contains only the $schema ref (all defaults)

Expected

The plugin's core contract is bounding the conversation. At minimum:

  • In-flight prune must actually reduce tokens before the request when near the model context limit (or prune thresholds are misconfigured/never fire in this mode)
  • Proactive compaction (lastCompaction) should trigger long before 229k
  • On unrecoverable context overflow, surface an error instead of a silent empty run with exit 0 (the orchestrator can't distinguish this from success)

Workaround in use

Orchestrator detects the empty-response loop and starts a fresh session (loses in-session continuity; conversation history only survives via the issue thread).

Cross-ref: initially misfiled as ranxianglei/billion-context#318 (environment there corrected — no bili proxy in this path; the state model investigation may still be relevant to acp-kernel).

State files and full logs available on request.

Activity

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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions