[Bug] Advisor tool result split across messages causes 400 on session resume
Bug Description
# Bug: 400 "advisor_tool_result must have a corresponding server_tool_use block before it" — server-tool pair split across separate messages, permanently breaks session resume
## Summary
The advisor server-side tool writes its server_tool_use block and its
advisor_tool_result block into two separate assistant message records in
the session transcript (.jsonl), instead of co-locating them in one assistant
message's content array the way the Anthropic API requires for server tools
(e.g. web_search). On the next turn / on resume, the assembled request is
rejected with a 400 and the session can no longer continue.
## Error
``
API Error: 400 messages.5.content.0: unexpected tool_use_id found in
advisor_tool_result blocks: srvtoolu_01A6WWxU6QWZXhrsgatkte5S. Each
advisor_tool_result block must have a corresponding server_tool_use
block before it.
`
## Environment
- Claude Code: 2.1.156
- Main-loop model: claude-opus-4-8 (advisor model: opus)
- Context: a long session that ran a background Workflow (~19 min) and made 2
advisor() calls; the failure surfaced after a context-summarization boundary.
## Root cause (from on-disk transcript inspection)
In the affected session transcript, each advisor call is stored as a split pair:
| Pair | server_tool_use | advisor_tool_result | Separation |
|---|---|---|---|
| srvtoolu_01E4Xr… | assistant msg (uuid 5f218a94) | a *different* assistant msg (uuid 486a1220) | adjacent records |
| srvtoolu_01A6WW… | assistant msg (uuid 51b94959) | a *different* assistant msg (uuid cdc715af) | separated by 6 system records |
The canonical server-tool format the API enforces is a single assistant message:
content: [ ..., {type:server_tool_use, id:X}, {type:advisor_tool_result, tool_use_id:X} ].
Because the two halves live in different message records, when the history is
re-assembled (especially after compaction collapses earlier messages), the
advisor_tool_result ends up at the start of a message with no server_tool_use
before it → 400.
## Reproduction conditions
1. Start a session and make an advisor() call (or several).
2. Keep the session running long enough that it crosses a context-summarization
boundary (a background Workflow run makes this easy to hit).
3. Continue / resume → 400 as above. The session is then stuck: every retry
re-sends the same invalid history and 400s again.
## Impact
- A session that has made advisor calls becomes **unrecoverable** once it crosses
the summarization boundary — no amount of retrying clears it.
- Any unsaved deliverable that was being returned on the failing turn is lost
unless it had already been written to disk (in our case a Workflow returned its
result as text on the turn that 400'd — see note below).
## Suggested fix
- When persisting an advisor (server-tool) call, write the server_tool_use and
its _tool_result into the **same** assistant message content array, result
immediately after use (matching the web_search server-tool representation).
- During compaction/summarization, treat a server_tool_use + its
_tool_result as an **atomic unit** — never summarize/drop one half while
keeping the other, and never reorder so the result precedes its use.
## Workaround (what recovered the session)
Manually edited the transcript .jsonl: for each split pair, appended the
advisor_tool_result block into the matching server_tool_use message's
content array, deleted the standalone result record, and repointed the orphaned
child's parentUuid to keep the linked-list thread linear. After that the session
re-validated and resumed. (Backed up the original first.)
## Related note
Separately, a background Workflow that ends with return {...}` delivers its
result as text to the main-loop turn rather than writing files; when that delivery
turn is the one that 400s, the entire workflow output is stranded (recoverable
only from the per-agent run journals). Co-locating the advisor pair fixes the
crash; consider also documenting that Workflow results are returned-not-persisted.
Environment Info
- Platform: darwin
- Terminal: vscode
- Version: 2.1.156
- Feedback ID: 35662791-d87c-4f3b-bb61-fc8caa95eb7f
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_01A6WWxU6QWZXhrsgatkte5S. Each `advisor_tool_result` block must have a corresponding `server_tool_use` block before it.\"},\"request_id\":\"req_011CbWUdGwCnJN1izcFQSzaB\"}\n at generate (/$bunfs/root/src/entrypoints/cli.js:11:63816)\n at makeRequest (/$bunfs/root/src/entrypoints/cli.js:51:7694)\n at processTicksAndRejections (native:7:39)","timestamp":"2026-05-29T07:37:05.318Z"},{"error":"Error: 400 {\"type\":\"error\",\"error\":{\"type\":\"invalid_request_error\",\"m…
Note: Content was truncated.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗