Malformed/partial tool-call markup rendered as visible text instead of filtered
Claude Code bug: malformed/partial tool-call markup rendered as visible text
Summary
An assistant turn occasionally emits tool-invocation markup that is NOT wrapped in the
expected <function_calls> block (and omits the antml: element namespace). The API
returns it as a type:"text" content block, the harness fails to parse it as a tool
call, and the client renders the raw <invoke>/<parameter> tags verbatim to the user
(looks like leaked HTML/XML). It also produces a 'tool call was malformed' retry.
Reproducible pattern (the headline)
- 15 occurrences in one long-running session, ALL identical in shape.
- Every instance is the literal stray token
count+ newline, immediately followed by
a bare <invoke name="Bash"> with no enclosing <function_calls> wrapper.
- All stored as content blocks of
type:"text"(nottool_use) — so nothing
downstream reclassified them; the client just printed the text.
- Strongly correlated with a long homogeneous loop: the same large prompt was
re-sent on a fixed cadence many times; the slip clustered there (format drift).
Instances (parameter VALUES redacted — only structure retained)
| # | session line | stray lead token | tool | param names |
|---|---|---|---|---|
| 1 | 9568 | 'count\n' | Bash | command, description, command, description |
| 2 | 9588 | 'count\n' | Bash | command, description, command, description |
| 3 | 9604 | 'count\n' | Bash | command, description |
| 4 | 9637 | 'count\n' | Bash | command, description |
| 5 | 9661 | 'count\n' | Bash | command, description |
| 6 | 9699 | 'count\n' | Bash | command, description |
| 7 | 9737 | 'count\n' | Bash | command, description |
| 8 | 9789 | 'count\n' | Bash | command, description |
| 9 | 9795 | 'count\n' | Bash | command, description |
| 10 | 9819 | 'count\n' | Bash | command, description |
| 11 | 9844 | 'count\n' | Bash | command, description |
| 12 | 9850 | 'count\n' | Bash | command, description |
| 13 | 9870 | 'count\n' | Bash | command, description |
| 14 | 9894 | 'count\n' | Bash | command, description |
| 15 | 9901 | 'count\n' | Bash | command, description |
Redacted skeleton of a single instance
count
<invoke name="Bash">
<parameter name="command">[REDACTED — shell command]</parameter>
</invoke>
(Genuine emissions had 2 or 4 such <parameter> blocks; values omitted.)
Minimal synthetic repro for the RENDER half (deterministic)
Feed the client an assistant message whose text block contains partial tool markup:
{"type":"assistant","message":{"role":"assistant","content":[
{"type":"text","text":"count\n<invoke name=\"Bash\">\n<parameter name=\"command\">echo hi</parameter>\n</invoke>"}
]}}
Expected: stripped or surfaced as a structured parse error.
Actual: raw <invoke>/<parameter> tags render verbatim in the transcript.
Environment
- Claude Code CLI, model Opus 4.8 (claude-opus-4-8), darwin.
- (Session transcript path, prod host details, and command bodies intentionally omitted.)
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗