[Bug] Server tool result separated from tool use by interleaved system messages
Bug Description
Title: 400 "advisor_tool_result must have a corresponding server_tool_use before it" — server-tool pair split by interleaved system messages
What happened:
The advisor server-side tool was invoked. While the call was in flight (advisor
calls are slow by design), I ran the /usage slash command and dismissed a settings
dialog. The harness inserted two system messages BETWEEN the server_tool_use
block and its advisor_tool_result block, splitting the pair across two separate
assistant messages. From then on, every request fails with:
API Error: 400 messages.5.content.0: unexpected tool_use_id found in
advisor_tool_result blocks: srvtoolu_01NPX9viXUtp11sh15miryMB. Each
advisor_tool_result block must have a corresponding server_tool_use block
before it.
The session is now permanently wedged — the malformed history is replayed on
every turn.
Evidence (session transcript JSONL, consecutive lines):
[360] assistant: server_tool_use(name=advisor, id=srvtoolu_01NPX9…)
[361] system: <command-name>/usage</command-name>
[362] system: <local-command-stdout>Settings dialog dismissed</…>
[363] assistant: advisor_tool_result(id=srvtoolu_01NPX9…)
Expected:
A server_tool_use block and its *_tool_result must remain adjacent (same assistant
message, as with web_search). The harness must not interleave slash-command output
or UI events between them — either queue interactive commands until the in-flight
server tool completes, or re-assemble the pair adjacently before sending.
Impact:
Unrecoverable session without manually editing the transcript .jsonl. Repro:
invoke advisor, then run any slash command / dismiss a dialog before it returns.
Environment: Claude Code, model claude-opus-4-8[1m], macOS (Darwin 25.6.0).
Environment Info
- Platform: darwin
- Terminal: Apple_Terminal
- Version: 2.1.216
- Feedback ID: ab58b374-2587-4f8b-a63b-688b5d77f90e
Errors
[{"error":"Error: 400 {\"type\":\"error\",\"error\":{\"type\":\"invalid_request_error\",\"message\":\"messages.5.content.0: unexpected `tool_use_id` found in `advisor_tool_result` blocks: srvtoolu_01NPX9viXUtp11sh15miryMB. Each `advisor_tool_result` block must have a corresponding `server_tool_use` block before it.\"},\"request_id\":\"req_011CenMP879JYeFmbaPX3caZ\"}\n at generate (/$bunfs/root/src/entrypoints/cli.js:40:48982)\n at makeRequest (/$bunfs/root/src/entrypoints/cli.js:80:7690)\n at processTicksAndRejections (native:7:39)","timestamp":"2026-09-06T14:34:58.716Z"},{"error":"Error: 400 {\"type\":\"error\",\"error\":{\"type\":\"invalid_request_error\",\"message\":\"messages.5.content.0: unexpected `tool_use_id` found in `advisor_tool_result` blocks: srvtoolu_01NPX9viXUtp11sh15miryMB. Each `advisor_tool_result` block must have a corresponding `server_tool_use` block before it.\"},\"request_id\":\"req_011CenQ3hMh8WkLzULEcu9Nu\"}\n at generate (/$bunfs/root/src/entrypoints/cli.js:40:48982)\n at makeRequest (/$bunfs/root/src/entrypoints/cli.js:80:7690)\n at processTicksAndRejections (native:7:39)","timestamp":"2026-09-06T15:09:55.745Z"}]
3 Comments
This is a dup of #86198
Another specimen of the same split, this time caused by a plugin (Mod) message injected mid-turn while
advisorwas in flight. Claude Code 2.1.296, macOS.Transcript order (
*.jsonl):| line | time (UTC) | entry |
|---|---|---|
| 1003 | 14:36:21 | assistant
server_tool_usename=advisor id=srvtoolu_01Qv34…(message.id…NfWeDLCkaa) || 1004 | 14:37:53 | user,
isMeta: true,origin: {kind: "plugin", name: "pr-status"}: plugin notification text || 1005 | 14:37:56 | assistant
advisor_tool_resultforsrvtoolu_01Qv34…(same message.id…NfWeDLCkaa) |Every request after that fails with:
/compactfails the same way. Note that a later message from the same plugin (sent between turns) was recorded correctly as a queued user turn; only the one that arrived during the advisor call was interleaved.This is the third time we've hit it (each time a plugin/monitor notification overlapping the 1–2 min advisor wait).
Workaround that worked: with the session closed, delete the interleaved entry (line 1004) and set the
parentUuidof theadvisor_tool_resultentry (line 1005) to theuuidof theserver_tool_useentry (line 1003).claude --resume <id>then works. Expected fix: hold mid-turn injected messages until the server tool result has been appended (or attach them after the whole assistant message).Same bug, a second trigger, still present in 2.1.293 on Windows (CLI, model claude-opus-5-5 with advisorModel claude-opus-5-5, effort medium).
Trigger: a user entry, not a slash command or a system message. An inbound message (a cross-session message, delivered as a user turn) arrived while the advisor call was in flight. The pair was split the same way.
Transcript, consecutive entries (2026-10-08, UTC):
| line | time | entry |
|---|---|---|
| 409 | 00:33:19.160 | assistant:
server_tool_usename=advisor, idsrvtoolu_01LgLaXiADQ54t97vJsHjFix|| 410 | 00:33:57.431 | user entry (text block), parented to 409; the advisor call was 38 s in |
| 411 | 00:34:53.718 | assistant (same message id as 409):
advisor_tool_resultforsrvtoolu_01LgLaXiADQ54t97vJsHjFix, parented to 410 |The turn finished normally (end_turn at 00:36:13). Every request after that failed:
Six failures, the same index each time. Request ids:
req_011CfoqL1JXg7W9vFc7KXHx1,req_011CfoqQuX9irejPRyyDLLNW,req_011CfoqTLhHWQGGowrqstfKJ,req_011CfoqV4rbBWENWB8iGs2DY,req_011CfoqVtbUjLQVcx3Fi5GzN,req_011Cfoqahz9kyhYW3EDJLs6K./advisor offdoes not recover. It printed "Advisor disabled", and the very next turn failed with the same 400. It leaves the storedserver_tool_use/advisor_tool_resultblocks in the history. Only restarting the session recovered it.Two suggestions: keep any inbound user or queued message out of an in-flight server-tool pair, as asked above; and make
/advisor off, or any 400 of this shape, strip or repair the orphaned advisor blocks, so the session can continue.