Malformed/partial tool-call markup rendered as visible text instead of filtered

Resolved 💬 1 comment Opened Jun 18, 2026 by trodrigu Closed Jun 18, 2026

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" (not tool_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.)

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗