Claude ACP v2 token spending overwrites context occupancy and blocks provider switches#22407
What happened
Switching a long-running thread from Codex back to Claude Max ACP repeatedly fails with:
| 1 | Insufficient context allowance for the provider handoff. Compact the target conversation or use a larger-context model; the current request has not been truncated. |
Both Sonnet and Opus fail. Switching back to Codex works.
Diagnosis
T3 treats the total token consumption reported when an ACP v2 turn ends as the conversation’s current context occupancy.
In this release, runtimeModel.ts maps an idle state_update.usage.totalTokens to {usedTokens: totalTokens}. The shared ACP adapter replaces its context-usage snapshot with that value, without retaining the window size from usage_update.
The installed Claude ACP agent 0.92.0 accumulates input, output and cache counters across model requests in the turn. Its terminal usage reports consumption; it separately reports context occupancy and capacity through usage_update.used/size.
The affected provider thread stores {"usedTokens":1303139}, with no maxTokens. Its native transcript’s last two distinct assistant requests report 651,373 and 651,766 tokens. Their sum is exactly 1,303,139.
The registry adapter supplies no model-window override here. Consequently, handoffBudget uses a 128,000-token fallback, subtracts the inflated consumption count and returns zero. T3 refuses the handoff before Claude receives the prompt.
The correction should keep turn consumption separate from context occupancy and preserve capacity reported through usage_update.
Steps to reproduce
Observed sequence; no fresh, isolated deterministic reproduction was run:
- Use Claude ACP 0.92.0 through a local registry instance with T3’s default ACP v2 mode.
- Complete a long turn containing multiple model requests and substantial cache reads.
- Switch to Codex, then back to the same Claude ACP instance.
- Send a short message. The handoff fails; changing the Claude model does not recover it.
Version
Desktop and server: 0.1.1-nightly.20261020.3411, release commit d36b7da2485bc889b320a285deea181f637d760a.
Environment
macOS darwin 27.0.0, arm64. Nightly desktop hosting the local server. Local registry instance running @agentclientprotocol/claude-agent-acp 0.92.0 with @anthropic-ai/claude-agent-sdk 0.3.300 and a Claude Max profile. Native Claude CLI: 2.1.304.
Evidence
Read-only inspection of statev2.sqlite and the native transcript:
| 1 | 2026-10-20 17:00:07 UTC run 1542 ACP / sonnet failed |
| 2 | 2026-10-20 17:00:31 UTC run 1543 ACP / opus failed |
| 3 | |
| 4 | Saved ACP contextUsage: {"usedTokens":1303139} |
| 5 | Saved maxTokens: absent |
| 6 | 651373 + 651766 = 1303139 |
| 7 | |
| 8 | Latest native request: |
| 9 | input_tokens=2 |
| 10 | cache_read_input_tokens=648077 |
| 11 | cache_creation_input_tokens=3506 |
| 12 | output_tokens=181 |
| 13 | total=651766 |
| 14 | |
| 15 | Latest prepared Codex-to-ACP handoff: |
| 16 | 15 historical items; 6558 characters of message text; delivery absent |
Related issues
- #20166: similar failure from missing capacity on Cursor/Grok; different accounting source.
- #22198: same error after native Claude session replacement.
- #19414: open deferred-handoff recovery work, unmerged when checked.
No confirmed duplicate of this ACP terminal-usage overwrite was found.
Fix applied or workaround
With approval, switched the same app thread to the configured native Claude Max provider using the same Max profile, and selected Opus 5.5.
Verification run 1546 used claudeAgent_max_usage / claude-opus-5-5, completed at 2026-10-20T17:16:00.705Z, and returned CLAUDE_MAX_NATIVE_OK. Verified the persisted completed run and visible reply. Restored the user’s unsent draft.
The native-provider workaround is verified. The ACP defect remains. No T3 source patch or direct SQL write was applied.
Filed by
Codex, GPT-6, via t3 triage.