[BUG] Tool calls intermittently emitted as plain text ("could not be parsed")
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?
During a long coding session, Claude Code intermittently fails to emit a tool
call as a real structured invocation. Instead, the tool-call markup leaks into
the assistant's visible message as plain text (e.g. a stray token like card
followed by a literal <invoke name="Bash">…</invoke> block), and the runtime
reports:
The model's tool call could not be parsed (retry also failed).
The automatic retry also fails, so the intended action (an Edit, Bash, Write, or
AskUserQuestion call) never runs and the turn stalls. The user sees the raw,
unparsed tool-call markup in the transcript and has to nudge ("继续" / "are you
stuck?") to get a retry.
It was not random — it correlated strongly with certain tool-call shapes:
- Long Edit old_string/new_string containing HTML/JSX with many special
characters (<, >, &, ${...}, backticks, quotes).
- Bash commands containing
${...},<,>, here-strings/heredocs, or pipes
mixed with quotes.
- Large AskUserQuestion payloads (multiple questions, long mixed CN/EN labels
with special characters).
- Several tool calls emitted back-to-back in one turn.
Short, simple tool calls (e.g. a one-line grep with no special characters)
almost never triggered it. Over a long session it happened many times and
severely slowed work; the only reliable workaround was to stop calling the
tools directly and delegate all edits/commands to sub-agents instead.
What Should Happen?
A tool call should always be emitted as a well-formed structured tool
invocation, regardless of how long its arguments are or how many special
characters (<, >, &, ${...}, backticks, quotes) they contain.
Specifically:
- Editing a file via Edit/Write with a large HTML/JSX/template-literal block
should reliably produce a real Edit/Write call — never leak the call into the
visible assistant message as plain text.
- If serialization of a tool call ever fails, the automatic retry should recover
and successfully emit the call — instead of surfacing the raw <invoke markup to the user and stalling the turn with "The model's tool
name="...">
call could not be parsed (retry also failed)."
- The action the user requested (the edit, the command, the question) should
actually execute, not silently no-op.
Error Messages/Logs
The model's tool call could not be parsed (retry also failed).
Visible leaked markup looked like (reconstructed):
card
<invoke name="Bash">
<parameter name="command">grep -c lookupScript src/templates/seo-pages.ts</parameter>
<parameter name="description">count lookupScript</parameter>
</invoke>
Steps to Reproduce
Note: this is intermittent; no minimal deterministic repro was isolated. It
appears tied to output length + special-character density in the tool-call
arguments. Observed pattern:
- In a long session, open a large TypeScript file (~300KB) that uses big
template-literal HTML blocks.
- Ask Claude to make an Edit whose old_string/new_string is a ~20+ line HTML/JSX
block containing ${...}, backticks, <a href="...">, —, etc.
- Intermittently, the Edit (or a following Bash / AskUserQuestion) is rendered
as visible plain text beginning with a stray token (e.g. card) followed by
literal <invoke name="...">...</invoke> markup.
- The runtime prints "The model's tool call could not be parsed (retry also
failed)"; the intended action does not run and the turn stalls.
Frequency increased with: longer arguments, more special characters, and several
tool calls emitted in one turn.
Claude Model
Opus
Is this a regression?
Yes, this worked in a previous version
Last Working Version
_No response_
Claude Code Version
2.1.196
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Warp
Additional Information
_No response_