### Preflight Checklist
- [x] I have searched existing issues. Similar reports …exist (#61122, #61367, #62344, #63616), but this report adds detailed JSONL evidence from one session with 23 malformed Bash calls.
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code available to me (`2.1.158 (Claude Code)` currently installed). The affected transcript contains failures on both `2.1.156` and `2.1.158`.
### What's Wrong?
In a long Claude Code session, intended Bash tool calls were intermittently emitted as ordinary assistant text instead of structured `tool_use` objects. The UI showed raw invoke text like:
```text
call
<invoke name="Bash">
<parameter name="command">...</parameter>
<parameter name="description">...</parameter>
<parameter name="dangerouslyDisableSandbox">true</parameter>
</invoke>
```
Because these records are plain `text` content instead of structured `tool_use`, Claude Code does not dispatch the Bash command. There is no `tool_use_id` and no matching `tool_result`.
This caused repeated false progress in one repo workflow: commits, verification commands, pushes, PR creation, PR merge, and cleanup commands were printed but not actually executed.
Important detail from the JSONL: one affected assistant message has `stop_reason = "tool_use"`, but its content still contains only ordinary text and no `tool_use` object.
### What Should Happen?
When Claude intends to run Bash, Claude Code should receive a structured `tool_use` object, execute the command, and append a matching `tool_result`.
If the model emits malformed tool-call text, Claude Code should surface an explicit parsing/tool-call error or reprompt internally. Raw `<invoke name="...">` blocks should not be rendered as normal assistant prose or fed back into future context where they may cause cascading failures.
### Error Messages/Logs
```shell
No shell error is shown, because the command is never dispatched.
Representative malformed JSONL shape:
{
"type": "assistant",
"message": {
"content": [
{
"type": "text",
"text": "...\\n\\ncall\\n<invoke name=\"Bash\">\\n<parameter name=\"command\">MAIN=...\\n...</parameter>\\n<parameter name=\"description\">Pull merged main and verify files</parameter>\\n<parameter name=\"dangerouslyDisableSandbox\">true</parameter>\\n</invoke>"
}
],
"stop_reason": "end_turn"
}
}
There is no tool_use object, no tool_use_id, and no following tool_result.
```
### Steps to Reproduce
This is intermittent, but the affected local transcript provides a concrete session-level reproduction/evidence trail:
1. Use Claude Code on macOS with Opus in a long repository workflow involving repeated Bash calls.
2. In the affected session, ask Claude to perform normal git/test/PR workflow actions such as commit, verify, push, create PR, merge PR, and cleanup.
3. After the session becomes long-context, observe that some intended Bash calls are printed to the conversation as raw text beginning with `call` and `<invoke name="Bash">`.
4. Inspect the session JSONL and compare normal versus malformed turns:
- Normal: `content[].type = "tool_use"`, `name = "Bash"`, has `id`, followed by matching `tool_result`.
- Malformed: `content[].type = "text"` containing raw `<invoke name="Bash">...`, no `tool_use_id`, no matching `tool_result`.
5. Verify downstream state: earlier printed commands had no effect. In this transcript, later turns confirm commit was not made, regression log did not exist, remote branch was absent, PR was not created, PR stayed open, and cleanup was not done.
Concrete analyzed transcript:
- Project: `texas-holdem-poker-recorder`
- Session id: `1931487f-0ac9-47fe-b759-5ba244821147`
- Local JSONL path pattern: `<home>/.claude/projects/-Users-<user>-playground-texas-holdem-poker-recorder/1931487f-0ac9-47fe-b759-5ba244821147.jsonl`
JSONL evidence summary:
- Total JSONL lines analyzed: 2,233
- Normal assistant structured tool uses: 347
- Normal tool results: 347
- Malformed raw invoke blocks: 23
- Affected tool: `Bash`
- All malformed blocks start with stray text `call` before `<invoke name="Bash">`
- First malformed block: `2026-05-29T15:22:53.436Z`
- Last malformed block: `2026-05-30T04:45:09.672Z`
- Versions:
- `2.1.156`: 22 malformed blocks
- `2.1.158`: 1 malformed block
- `stop_reason` values:
- `end_turn`: 22
- `tool_use`: 1, but still no structured `tool_use` object
- Affected turns had very high cache-read tokens, roughly 441k-489k, suggesting long-context state may be related.
Representative affected turns:
| JSONL line | Timestamp UTC | Version | stop_reason | Intended Bash description |
|---:|---|---|---|---|
| 1807 | 2026-05-29T15:22:53.436Z | 2.1.156 | tool_use | Commit temp-player fix |
| 1908 | 2026-05-29T16:16:04.950Z | 2.1.156 | end_turn | Typecheck + component test + build after 2-card placeholder |
| 2038 | 2026-05-29T16:32:17.752Z | 2.1.156 | end_turn | Push branch to origin |
| 2081 | 2026-05-29T16:34:03.745Z | 2.1.156 | end_turn | Create PR with simple body |
| 2115 | 2026-05-29T16:35:29.605Z | 2.1.156 | end_turn | Squash-merge PR #10 |
| 2141 | 2026-05-30T04:35:29.478Z | 2.1.156 | end_turn | Pull merged main and verify files |
| 2181 | 2026-05-30T04:45:09.672Z | 2.1.158 | end_turn | Update local main and verify final state |
### Claude Model
Opus
### Is this a regression?
Yes, this worked in a previous version
### Last Working Version
Unknown. I started seeing this after updating around 2026-05-29. The analyzed transcript shows failures on `2.1.156` and still one occurrence after `2.1.158`.
### Claude Code Version
`2.1.158 (Claude Code)` currently installed.
Affected transcript contains:
- `2.1.156`: 22 malformed raw invoke blocks
- `2.1.158`: 1 malformed raw invoke block
### Platform
Anthropic API
### Operating System
macOS
### Terminal/Shell
Other (`zsh`; terminal app unknown from the JSONL)
### Additional Information
Related public issues found before filing:
- #49747: Opus mixes legacy XML tool-use format into JSON tool calls on longer payloads. This appears to be the broader/root issue. Later comments also describe full raw `<invoke>` blocks being rendered as visible text, missing `tool_use` despite `stop_reason = "tool_use"`, and continued reproduction on Opus 4.8.
- #61122: Bash tool call rendered as raw XML instead of executing
- #61367: Intermittent malformed tool calls emitted as plain text instead of structured `tool_use`, then cascades via retry
- #62344: Malformed tool calls in long sessions due to in-context few-shot poisoning
- #63616: Claude Code fails BASH invocations, reported on `2.1.156`
Suggested investigation areas:
- Add a client-side invariant: if `stop_reason = "tool_use"`, assistant content must contain at least one structured `tool_use` object.
- Detect raw `<invoke name="...">` blocks in assistant text and treat them as malformed tool calls.
- Avoid feeding raw malformed tool-call text back into future context.
- Investigate whether long-context sessions with high cache-read tokens increase the chance of malformed tool-call serialization.