[BUG] Server-side tool (advisor) bricks session: auto-rename system-reminder injected between server_tool_use and tool_result causes 400
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Two of my sessions became permanently un-resumable: every request 400s on resume with this error:
API Error: 400 messages.11.content.0: unexpected `tool_use_id` found in `advisor_tool_result` blocks: srvtoolu_015YcHgq8WqbJiXxMe3VqpBv. Each `advisor_tool_result` block must have a corresponding `server_tool_use` block before it.
Root cause (verified from the session .jsonl transcripts):
The advisor tool is a server-side tool (srvtoolu_ prefix). Its server_tool_use call block and advisor_tool_result block must stay in a single atomic assistant turn, the API requires each advisor_tool_result to be immediately preceded by its matching server_tool_use.
Advisor calls are slow (1.5 to 3.5 min in my transcripts). During that in-flight window, the session auto-rename feature injected a <system-reminder> user message ("The user named this session ...") between the server_tool_use and the advisor_tool_result. That split the atomic turn into three transcript records:
assistant: [server_tool_use advisor]
user: [<system-reminder> "The user named this session ..."] <-- INJECTED mid-flight
assistant: [advisor_tool_result] <-- now orphaned
On the next request the advisor_tool_result is the first block (content.0) of a standalone assistant message with no preceding server_tool_use, so the API rejects the whole conversation with the 400 and the session can no longer be resumed.
Evidence: Identical signature in both bricked sessions. The auto-rename reminder timestamp falls squarely inside the advisor round-trip:
| Session | server_tool_use | injected rename reminder | advisor_tool_result |
|---|---|---|---|
| A (named "la-entity") | 04:12:45Z | 04:14:29Z "named this session" | 04:14:30Z |
| B (named "web-ios-parity") | 04:26:27Z | 04:28:01Z "named this session" | 04:28:51Z |
In the same sessions, advisor calls that completed with nothing injected between the two blocks worked fine (the result block's parent was directly the call block). The only difference between the broken and working advisor calls is whether the async session-naming reminder happened to land mid-flight. It was specifically the one-time session-naming reminder in both cases (fires once, early, asynchronously), which is why it tends to collide with an early advisor call.
What Should Happen?
Claude Code should never enqueue an injected user message (the session-rename <system-reminder>, or any other) between a server_tool_use block and its corresponding *_tool_result block. The in-flight server-tool turn should remain atomic, and the session should stay resumable.
Error Messages/Logs
API Error: 400 messages.11.content.0: unexpected `tool_use_id` found in `advisor_tool_result` blocks: srvtoolu_015YcHgq8WqbJiXxMe3VqpBv. Each `advisor_tool_result` block must have a corresponding `server_tool_use` block before it.
Steps to Reproduce
This is a timing-based race, so it is not deterministic, but the recipe that triggered it twice:
- Start a brand-new session (so the one-time auto-rename has not yet fired).
- Have the model invoke a slow server-side tool early in the session. In my case this was the
advisortool, whose calls always take minutes because they forward the whole transcript to a stronger model. Any server-side tool with a multi-second round-trip widens the window. - While that server-tool call is in flight, the asynchronous session auto-rename completes and injects its
<system-reminder>user message ("The user named this session ..."). - If that injection lands between the
server_tool_useand the*_tool_result, the turn is split. The next request (or any resume) 400s with the error above and the session is permanently un-resumable.
The wider the server-tool latency, the more reliably step 3 collides with step 2.
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
(not known)
Claude Code Version
2.1.156 (Claude Code)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
iTerm2
Additional Information
Diagnosed directly from the session .jsonl transcripts (two separate affected sessions, identical signature).
Suggested fix: defer injected user messages (auto-rename <system-reminder>, etc.) until any in-flight server-tool turn completes, rather than wedging them between a server_tool_use and its *_tool_result. A defensive repair on resume (drop an orphaned *_tool_result, or the wedged reminder) would also un-brick existing affected transcripts.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗