claude-code - 💡(How to fix) Fix [Bug] Advisor tool result split across messages causes 400 on session resume

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Error Message

[{"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…

Root Cause

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:

Pairserver_tool_useadvisor_tool_resultSeparation
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.

Fix Action

Fix / Workaround

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:

Pairserver_tool_useadvisor_tool_resultSeparation
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.

Code Example

[{"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…
RAW_BUFFERClick to expand / collapse

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:

Pairserver_tool_useadvisor_tool_resultSeparation
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.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix [Bug] Advisor tool result split across messages causes 400 on session resume