claude-opus-4-8: malformed tool-call wrapper (raw <invoke> XML leaks as text, tool call fails) + off-topic/hallucinated replies since ~2026-06-26
Status Open
Reported on v2.1.187
Maintainer reply None cached
Workaround ✓ Mentioned in description ↑
Activity 5 comments · opened Jun 28, 2026
Environment
- Claude Code desktop app (entrypoint claude-desktop), updated to latest; bundled claude-code 2.1.187. Bug persists after updating.
- Windows 11 (10.0.26200)
- Model: claude-opus-4-8 (used in all sessions)
- Endpoint: https://api.anthropic.com (official, no proxy)
- Reasoning effort: high (extended thinking on)
Summary
Since ~2026-06-26/27, claude-opus-4-8 intermittently produces two coupled failures:
- Malformed tool calls. Instead of a structured
tool_useblock, output is stored as a single plain text block containing raw tool-call XML (a stray tokencourtfollowed by<invoke name="..."><parameter ...>...</invoke>). Notool_useblock is produced, so the client has nothing to execute → the tool call fails and the raw XML is shown verbatim in the conversation. - Off-topic / hallucinated replies including content the user never said (context confusion).
Evidence (session transcript .jsonl)
- Leaking assistant message:
stop_reason = "tool_use"butmessage.contentis a singletextblock with NOtool_useblock; text contains literal `court
<invoke name="Write">...</invoke>. model = claude-opus-4-8`.
- The wrapper that should be
<function_calls>appears corrupted ascourt.
Onset & frequency
- Clean before ~06-26 (only one occurrence on 06-17, in an extreme 13,410-line / 1,539-thinking-block session).
- Frequent on 06-27 and 06-28, including moderate sessions (~1,100–1,400 lines). Intermittent within a session; worse in longer/heavier sessions and with large tool payloads (Write/Workflow content).
Ruled out
- Client version: updating the desktop app to latest did NOT fix it.
- User config: settings.json clean (no hooks, output styles, or injected system prompt).
- Project/data: no
<invoke>text anywhere in the repo; local headlessclaude -pexecutes tools normally.
Workaround
- Switching the model from Opus 4.8 → Opus 4.7 (same session, same machine) immediately restores correct tool execution AND coherent on-topic replies. Strongly indicates a claude-opus-4-8 server-side regression.
Impact
Severe: tool calls fail and work is blocked; off-topic replies waste turns. Had to abandon Opus 4.8 and fall back to 4.7.
5 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Your transcript-level evidence nails the client-side half of this, and it points to the part that's actually dangerous, which I'd flag loudly: this is a silent no-op that looks like success.
When
stop_reason = "tool_use"butmessage.contentis a singletextblock with the raw<invoke …>XML and notool_useblock, the client has nothing to execute — so the tool did not run. But the model's surrounding prose will usually still say "I've written the file / made the change," and the leaked XML scrolls past. So for aWrite/Edit/Workflowpayload that leaks this way, the file was never written even though the turn reads as if it succeeded. That's the same silent-success-failure class as the fabricated/unexecuted tool-call reports (this looks related to #68354 / #70544, and to the broader "model narrates a tool result that never happened" pattern).Practical takeaway while it's unfixed server-side:
court+ raw<invoke>leak, check that the files/edits actually exist on disk (git status, timestamps, re-open the file). Don't assume the Write landed. A leakedWriteis the high-stakes case — it's data you think you saved and didn't.<invoke>block as a hard signal to re-issue that step, not continue — the model may keep building on a file state it believes exists.On reducing the trigger rate (your onset data — frequent since ~06-26, worse in long/heavy sessions, large Write/Workflow payloads, extended thinking on — lines up with a context/thinking-pressure failure mode):
MAX_THINKING_TOKENS=8000(or off) for sessions that do a lot ofWrite/Workflow. The leak correlating with high reasoning effort + large tool payloads suggests the wrapper corruption surfaces under thinking+big-output pressure./clearor/compactbefore a largeWrite/Workflowstep so the tool call is emitted with less accumulated context.Write/Workflowbody into smaller writes reduces the per-call output size that seems to correlate with the corruption.None of these are a fix (the malformed wrapper is model/server-side, and as you confirmed, updating the client doesn't help) — they just lower the probability and, more importantly, the verify-after habit stops a leaked
Writefrom quietly costing you work.the same issue
Sharing forensic data that may help narrow this down. Ran a full scan of local session logs (
~/.claude/projects/**/*.jsonl) covering ~2 months (2026-05 to 2026-07), ~122k assistant messages across several models on the same client install, looking for text blocks containing literal<invoke name=...>markup (missing theantml:namespace prefix) wherestop_reasonwas stilltool_use.Model correlation is very strong — this looks opus-4-8-specific, not client/version-specific:
| Model | assistant messages | leaks |
|---|---|---|
| claude-opus-4-8 | 95,086 | 54 (100% of all leaks) |
| claude-fable-5 | 13,503 | 0 |
| claude-opus-4-7 | 9,365 | 0 |
| claude-haiku-4-5 | 2,467 | 0 |
| claude-sonnet (4-6 / 5) | 1,489 | 0 |
54/54 leaks landed on opus-4-8; zero across ~28k messages on other models in the same window, same client, same local config. If the leak rate were model-independent, ~12 leaks would be expected on the other models given their traffic share — none occurred.
Ruled out as causes (tested directly against the data):
<invoke>text existed anywhere earlier in the transcript — it originates fresh in a single generation, it isn't "learned" from earlier contextConsistent fingerprint across all 54 cases: the malformed message contains only a
textcontent block (no propertool_useblock), yet the API still reportsstop_reason: tool_usefor that turn — the stop-token signaling still "knows" a tool call was intended, but the call envelope itself got serialized as plain text without theantml:prefix. All 54 occurred immediately after athinkingblock, right at the prose→tool-call boundary, several with a stray one-word fragment just before it (e.g. "call" / "count" / "mark" in our transcripts — similar to the "court" token reported elsewhere in this issue family).Timing: weekly leak rate (per 1k opus-4-8 messages) sat around 0.0–0.3 through late June, dropped to ~0 for five straight days (Jul 2–6), then jumped to ~5–21/1k on Jul 7–10 — a sudden burst with no corresponding local change on our end. That lines up with #75740's "regression, ~1 week" timestamp (filed Jul 8).
Given the clean model-only correlation plus the "text-block-with-stop_reason:tool_use" fingerprint, this reads as a generation-time issue on the opus-4-8 serving path rather than client-side parsing — consistent with the
area:modellabeling already here and on #69529/#72015.Happy to share the aggregation script or raw per-incident stats if it's useful for triage.
@chengchangli — the elimination here is what makes this one stand out: client updated, settings clean, no <invoke> anywhere in the repo, headless claude -p fine — everything held constant except the model, and 4.7 fixed it instantly in the same session.
This has been open six weeks now — are you still pinned to 4.7, or did you move back up at some point?