[Bug] Advisor tool result split across messages causes 400 on session resume

Resolved 💬 2 comments Opened May 29, 2026 by traderose Closed Jun 1, 2026

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.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗