[Bug] v2.1.109 / Opus 4.7 — silent stuck-turn during tool execution (two distinct failure modes)

Status Fixed / completed
Maintainer reply None cached
Activity 9 comments · opened Apr 19, 2026 · closed Apr 19, 2026

[Bug] Claude Code v2.1.109 / Opus 4.7 — silent stuck-turn during tool execution (two distinct failure modes)

Summary

Running a long-lived interactive session via claude --channels plugin:telegram@claude-plugins-official under systemd, we hit the model in a permanently stuck state — stop_reason: tool_use but no follow-on activity. The session stops processing, no error is emitted, the process stays alive. Two distinct stuck flavors observed in a single day, both on the same agent doing the same task class.

Environment

  • Claude Code CLI: v2.1.109
  • Model: claude-opus-4-7 (1M context)
  • Host: Ubuntu 24.04 on AWS EC2 t3.micro (1.9 GB RAM)
  • Launched via: script -qec "claude --channels plugin:telegram@claude-plugins-official --dangerously-skip-permissions --disallowedTools mcp__telegram-mcp__tg_send" /dev/null under systemd Restart=always
  • Working directory: a git repo with CLAUDE.md, .mcp.json, a local .claude/skills/ tree
  • Effort level: CLAUDE_CODE_EFFORT_LEVEL=max
  • Auto-memory disabled: CLAUDE_CODE_DISABLE_AUTO_MEMORY=1
  • Auto-updater disabled: DISABLE_AUTOUPDATER=1

Failure mode A — Edit tool_use with no tool_result

When: 2026-04-19 11:13:43 UTC
Session: 1a642596-ee80-4d9e-bf8a-eee474d4e82a
Last JSONL assistant entry:

{
  "type": "tool_use",
  "id": "toolu_01NeNUJdzhBeeckre3Zxm5TD",
  "name": "Edit",
  "input": {
    "file_path": ".../skills/holder-scanner/scripts/scan_holders.sh",
    "old_string": "<263 chars, ASCII-only, a bash variable block>",
    "new_string": "<626 chars, ASCII-only, adds a sourced helper block>",
    "replace_all": false
  }
}

stop_reason: tool_use. No matching tool_result ever written to JSONL. File on disk untouched. Subsequent queue-operation enqueue entries from the TG plugin piled up but the session could not dispatch them (turn still open).

Preceding context: 14 tool calls (Bash, Grep, Read, Write chains) in the 90 seconds before the stuck Edit. No errors in any of those results.

Failure mode B — assistant never emits next message after a successful tool_result

When: 2026-04-19 09:36:29 UTC
Session: fc891dc4-a248-4d22-949e-3b061660c307
Last JSONL assistant entry:

{
  "type": "tool_use",
  "name": "Read",
  "input": {
    "file_path": ".../skills/holder-scanner/scripts/scan_holders.sh",
    "offset": 1,
    "limit": 40
  }
}

This is different from mode A. The tool_result WAS written (file content returned normally). But the model never produced the next assistant message — no text, no further tool_use, no end_turn. The stop_reason of that last assistant entry was tool_use, meaning the model expected to continue the turn. It just... stopped.

All tool_use/tool_result IDs matched cleanly (60/60). The turn was not closed. JSONL stopped growing except for a single queue-operation enqueue 7 minutes later when the user's follow-up message arrived (also never dispatched).

Shared signature

Both sessions exhibited tool_use:end_turn stop ratios far outside the norm:

| Session | tool_use stops | end_turn stops | Ratio |
|---|---|---|---|
| fc891dc4 (mode B, 09:36) | 60 | 2 | 30.0 |
| 1a642596 (mode A, 11:13) | 32 | 1 | 32.0 |
| Baseline across 10 healthy sessions Apr 17-18 | — | — | 3.0 — 7.0 |

So the stuck-turn correlates with the model chaining unusually many tools before the hang. Both runs involved heavy compound work (committing coordinated code changes after a peer review, touching multiple files).

What we ruled out

  • TG channel plugin is not involved — it only delivers inbound messages and handles the reply tool. The hang is upstream of message delivery, inside Claude Code's tool execution / turn generation.
  • bun subprocess was alive and healthy throughout both hangs.
  • MCP configuration — we cycled between ENABLE_TOOL_SEARCH=false (eager) and default (deferred), and between full .mcp.json and {"mcpServers": {}}. Both stuck-turns recurred across configurations.
  • Memory pressure — not at OOM; ~700 MB used of 1.9 GB. No OOM entries in dmesg/journal.
  • Edit payload in mode A is a straightforward ASCII text replacement in a .sh file, 626-char new_string, replace_all: false. Nothing unusual — no emoji, no regex specials, no huge size.
  • Disk state — project files fine, no I/O errors, the Edit never actually ran.

Request

  1. Is there telemetry / logging we can enable on the CLI to catch the handoff between model response and tool execution (mode A) and the handoff between tool_result and next model turn (mode B)?
  2. Is the 30x tool_use:end_turn ratio a known precursor to tool-execution hangs in v2.1.109 / Opus 4.7?
  3. Is there a way to surface the hang as an error (exit code, SIGTERM, or at least an error line in the JSONL) instead of silent freeze? Currently there's no signal from the CLI — the process stays running, the session stays "active," but no tool is executing and no assistant turn is advancing.

Happy to pull the full JSONLs and attach them to this issue if it helps. Both stuck sessions are preserved at:

  • /home/ubuntu/.claude/projects/-home-ubuntu-nolix/1a642596-ee80-4d9e-bf8a-eee474d4e82a.jsonl.stuck-20260419-edit1113
  • /home/ubuntu/.claude/projects/-home-ubuntu-nolix/fc891dc4-a248-4d22-949e-3b061660c307.jsonl.stuck-20260419

View original on GitHub ↗

9 Comments

github-actions[bot] · 4 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/47996
  2. https://github.com/anthropics/claude-code/issues/35773
  3. https://github.com/anthropics/claude-code/issues/44596

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

Axiom89 · 4 months ago

Update — same Edit payload succeeded in a different session (session-state-specific, not content-specific)

Follow-up to the two stuck-turns from earlier today. I reproduced the exact failure mode A Edit (toolu_01NeNUJdzhBeeckre3Zxm5TD, 2026-04-19 11:13:43 UTC) from a different Claude Code session on a different machine:

  • Original stuck session: Nolix agent on EC2 (long-lived systemd session, 32 tool_use stops : 1 end_turn, ~11 h uptime under channel-plugin + Opus 4.7). The Edit never returned a tool_result.
  • Reproduction: I scp'd scan_holders.sh to my Windows box, opened a fresh Claude Code session, called Edit with the exact same file_path / old_string (263 chars) / new_string (626 chars) / replace_all: false.
  • Result: Edit returned instantly. File written correctly. No hang.

So the content of the Edit isn't the trigger — the same bytes behave fine in a fresh session on a different host. Whatever is wedging the tool execution is carried by the Nolix session's accumulated state (long turn history, channel-plugin queue, many MCP subagents, high tool-use:end_turn ratio — all present in the stuck session and absent in my fresh repro session).

A few more observations from the stuck session that may help narrow it:

  1. Precursor: heavy tool chaining. The 90 seconds before the hang contained 14 tool calls (Bash/Grep/Read/Write), each with stop_reason: tool_use. Both stuck-turn instances today were preceded by similar bursts with tool_use:end_turn ratios of 30-32:1 — ~4-10× our historical baseline of 3-7:1.
  1. No signal on the wire. At the moment of hang: process alive, no CPU activity, Anthropic API socket open and idle, JSONL has the tool_use entry with stop_reason: tool_use and nothing after. The channel plugin's queue-operation enqueue entries for later user messages pile up in the JSONL because the turn is still "open" from Claude Code's perspective — model never got a tool_result to continue with, but also never got an error.
  1. Corroborating failure mode B. A 2nd stuck-turn in a separate session earlier same day (09:36:29 UTC, fc891dc4-...) showed the variant where the tool_result was written (Read of the same scan_holders.sh range) but the model never produced the next assistant message. stop_reason: tool_use on the preceding assistant, 60 tool_use stops vs 2 end_turn in that session. Same family of "model wedged mid-turn in a long tool chain," different point of wedge.
  1. Claude Code still thinks the session is healthy. No process exit, no error exit code from claude -p / --channels, no journald entry. The only observable recovery path is systemctl restart.

Best-guess hypothesis: under some condition reachable by long sessions with many MCP tools + long tool chains, the bridge between model-side tool_use emission and tool_execution / tool_result plumbing drops a message. No user-visible error, no retry, no timeout — the turn just stays half-open forever. A timeout + exit-on-stall would turn this silent hang into a loud failure we could at least auto-recover from.

Happy to share the full JSONLs privately if useful. Both stuck sessions preserved at:

  • /home/ubuntu/.claude/projects/-home-ubuntu-nolix/1a642596-ee80-4d9e-bf8a-eee474d4e82a.jsonl.stuck-20260419-edit1113
  • /home/ubuntu/.claude/projects/-home-ubuntu-nolix/fc891dc4-a248-4d22-949e-3b061660c307.jsonl.stuck-20260419
Axiom89 · 4 months ago

Response to the duplicate-check bot + new data point

Re: the three flagged candidates — they describe the same cluster of bugs but each captures only one facet:

  • #47996 (Skill tool → no next assistant after tool_result) = our failure mode B. Specific to Skill tool; ours sees the same pattern after Read.
  • #35773 (stops mid-task after ~7 sequential Edits) = our failure mode B again, sparse on detail. VSCode extension, Opus 4.6.
  • #44596 (Bash completes, no tool_result delivered) = our failure mode A, but for Bash. Ours is Edit.

This issue is not a duplicate of any one — it's an umbrella/upgrade with material new evidence:

  1. Both failure modes observed in the same 24h on the same session, with full JSONL evidence for each, preserved on disk for inspection.
  2. Opus 4.7 / 2.1.109 — none of the three candidates are on 4.7. This rules out "Opus-4.6-only" as an easy explanation.
  3. Session-state-specific reproduction (per my earlier comment): the exact same Edit payload that hung the long-running agent session succeeded instantly in a fresh Claude Code session on a different host. None of #47996/#35773/#44596 have that A/B evidence.
  4. Precursor signature varies, which weakens the "heavy tool chaining causes it" hypothesis:
  • Hang #1 (failure mode B, 09:36 UTC): tool_use:end_turn ratio = 30:1 in the session
  • Hang #2 (failure mode A, 11:13 UTC): ratio = 32:1, Edit with 263→626-char ASCII replacement
  • Hang #3 (failure mode A, 12:12 UTC — new, captured after the comment above): ratio = 6.8:1 (healthy), Edit on the same file with 317→5480-char new_string containing non-ASCII box-drawing chars (─ ═ ║)

New data point — Hang #3 (failure mode A recurrence 2 hours after the first two)

  • Session: 6276dfc2-7fff-4a98-96f8-e81e725a40fa (the session that started after we restarted to recover from Hang #2)
  • Tool: Edit, id toolu_012MGe1GuMdGZZhzk3hRX6M4
  • File: same scan_holders.sh
  • Stuck tool_use logged at 2026-04-19T12:12:14Z, stop_reason: tool_use
  • No matching tool_result ever written; JSONL frozen for 5 min before systemd restart
  • Precursor ratio was healthy this time (6.8:1) — so the "long tool chain" theory from the first two doesn't apply
  • The new_string contained 5480 chars including box-drawing glyphs for a section header (# ──────...)
  • A 4th candidate variable to examine: large new_string (5480 chars) + non-ASCII

Preserved at: /home/ubuntu/.claude/projects/-home-ubuntu-nolix/6276dfc2-7fff-4a98-96f8-e81e725a40fa.jsonl.stuck-20260419-edit1212

Asks

  1. Please keep this issue open as the umbrella. I can triangulate across the three cluster issues on behalf of triage.
  2. Per my previous comment's ask — please consider instrumenting a timeout + loud failure in the model↔tool_execution bridge. After three observed hangs in one day on one agent, I can confirm systemctl restart is the only recovery path — no exit code, no exit_reason, no stderr from the CLI.

👎'ing the auto-close comment to prevent the 3-day auto-closure.

Axiom89 · 4 months ago

Important correction — the affected agent was running v2.1.109, not latest

Shortly after my last comment I noticed the hanging agent (Nolix) was pinned to v2.1.109 (Apr 15 release) via DISABLE_AUTOUPDATER=1 in its systemd unit — a policy chosen months ago to prevent restart cycles after the npm→native migration.

Which means it has been running 3 versions behind for 3 days and has not received the v2.1.113 fix:

v2.1.113: "Subagents that stall mid-stream now fail with a clear error after 10 minutes instead of hanging silently"

…which reads exactly like our symptoms, plus the native-binary refactor in v2.1.113 that likely touches the tool-execution plumbing we were staring at.

I've upgraded the agent to v2.1.114 (install via claude install latest, symlink swapped, service restarted clean). Post-upgrade smoke test is healthy — bun subprocess alive, channel plugin serving, first interactive turn completed without orphaned tool_use. Going to run this agent on a deliberately heavy compound Edit workload next and report back.

Two outcomes possible:

  1. No recurrence → the bug is already fixed in 113/114; this issue can be closed with a note to users on frozen versions to check their DISABLE_AUTOUPDATER policy. My session that reproduced A/B "successfully" was running on the Windows 2.1.114 build — which would have actually been silently exercising the same post-fix code path. That's still a useful data point for anyone on frozen older builds.
  2. Still recurs on 114 → I'll post the new JSONLs and the issue stays open with a cleaner narrative.

Downgrading the severity of my earlier claim until the post-upgrade test run completes. Apologies for the initial "upstream bug" framing — when the version drift turned up, that framing got weaker than the evidence supports. Leaving the issue open for the test result.

Also worth flagging for triage: the fact that DISABLE_AUTOUPDATER=1 is documented in a fair number of long-lived-agent setups (ours, plus other community patterns we've seen) and silently freezes users on the old stream-hang code path is itself a product observation — worth a callout in the DISABLE_AUTOUPDATER docs that it does NOT just disable the updater prompt, it actually freezes you at the install-time version until you manually claude install latest. Easy to miss.

Axiom89 · 4 months ago

Closing — post-upgrade test passes, issue was version drift

15-min stress test on the upgraded agent (v2.1.114):

  • Compound multi-scoring Edit workload — exactly the pattern that hung v2.1.109 twice this morning
  • Bun PID stable the entire time, no stuck-turn recurrence
  • In-flight Edits resolved on every occurrence (3 moments where unmatched=1 briefly, all cleared within 60-90s as the tool_result came back — matches the v2.1.113 "stalled streams abort after 5 min" behavior)
  • Contrast with v2.1.109 earlier today: unmatched=1 stayed frozen indefinitely, required systemctl restart each time

Closing this as duplicate of whatever the v2.1.110–v2.1.113 fixes resolved internally. All three candidates the bot flagged (#47996, #35773, #44596) are also likely manifestations of pre-v2.1.113 stream-hang; worth noting that those reporters were all on 2.1.106–2.1.107 era.

Takeaway: DISABLE_AUTOUPDATER=1 silently froze the agent 3 versions behind the fix. If the Claude Code docs could add a one-liner to DISABLE_AUTOUPDATER explaining that users must manually claude install latest on a schedule (the env var doesn't queue updates, it just disables the prompt), that'd help long-lived-agent operators avoid this exact rabbit hole.

Mitigation shipped on our side: nightly version-check cron that flags outdated CLI in the agent's daily Telegram recap. Available as a pattern for anyone running similar setups.

Thanks for the triage — closing. If we see a recurrence on v2.1.114 I'll file fresh with clean JSONLs rather than resurrect this thread.

Axiom89 · 4 months ago

Closing — post-upgrade test passes. See final comment.

Axiom89 · 4 months ago

Filed #51927 as a focused follow-up on the surviving Mode A failure mode. Mode B appears fixed post-v2.1.113; Mode A persists across v2.1.114/2.1.116/2.1.117 on headless sessions with new diagnostic signatures and tested workarounds. Keeping discussion of the surviving mode there.

nestorcolt · 4 months ago

same problem here even opus 46

github-actions[bot] · 2 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.