Context compressor non-atomically splits server_tool_use/advisor_tool_result pairs, crashing session with 400
Status Closed — duplicate
Maintainer reply None cached
Activity 2 comments · opened Jul 25, 2026 · closed Aug 15, 2026
Summary
When context compression fires ('Crunched for Xs'), the compressor can drop a server_tool_use block while keeping its paired advisor_tool_result in a subsequent message. The next API call then fails with a 400 that cannot be retried, killing the session.
Error
messages.5.content.0: unexpected `tool_use_id` found in `advisor_tool_result` blocks: srvtoolu_0113SF3GSdjhpbcUPzkeVk5L. Each `advisor_tool_result` block must have a corresponding `server_tool_use` block before it.
Steps to reproduce
- In a long session, call the
advisortool (or any path that emits aserver_tool_useblock). - Continue working until context pressure triggers compression.
- If the compression boundary falls between the assistant message containing the
server_tool_useand the user message containing theadvisor_tool_result, the tool-use block is dropped but the result block survives. - The next turn sends an invalid history → 400 → session dead.
What I observed
- Claude Code tried model fallback: Opus 5 (1M) → Opus 5 → Sonnet 4.6. All three hit the same 400 because the history itself is corrupt, not the model.
- Triggering input was "continue executing plan" — an innocuous prompt that happened to be the first turn after compression.
Expected behavior
The compressor should treat server_tool_use + its corresponding advisor_tool_result as an atomic pair: either keep both or drop both (replacing both with a summary entry if needed).
Environment
- Claude Code version: (from session — exact version not captured)
- Branch:
jukim07/feat/clinician-playwright-fixtures - Model at time of crash: Opus 5 (1M context)
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗