Claude Code freezes: static spinner, unresponsive input, ignores SIGTERM
Status Open
Maintainer reply None cached
Workaround ✓ Mentioned in thread ↓
Activity 6 comments · opened Jan 24, 2026
Description
Claude Code occasionally enters a frozen state where:
- The animated spinner becomes static (stops animating)
- Input field stops accepting any input
- Escape does not cancel the current operation
- The process ignores SIGTERM (remains in
Rl+state) - Only SIGKILL terminates it
Reproduction
Observed twice in tmux sessions. Both times the session was running normally, then froze mid-operation.
Case 1: Context exhaustion
- Context at 5% remaining
- Status showed:
Ideating… (34m 23s · ↓ 0 tokens · thinking) - 0 tokens received for 34+ minutes
- Likely: API rejected the request due to context overflow, but client didn't handle the error/timeout
Case 2: Normal operation
- Context was normal (not exhausted)
- Status showed:
Pondering… (4m 4s · ↓ 7.7k tokens · thought for 2s) - 7.7k tokens were received, then froze
- The session was managing other tmux sessions via
tmux send-keyscommands
Environment
- Platform: Linux 6.8.0-90-generic
- Claude Code running inside tmux sessions
- Multiple concurrent Claude Code sessions active
Expected behavior
- Escape should cancel the current operation
- SIGTERM should gracefully terminate the process
- If the API connection drops, the client should timeout and show an error
Actual behavior
- Complete freeze: no animation, no input, no response to signals
- Only
kill -9works
Process state when frozen
bash(PID)---claude(PID)-+-{claude}(thread1)
|-{claude}(thread2)
|-{claude}(thread3)
|-{claude}(thread4)
|-{claude}(thread5)
|-{claude}(thread6)
|-{claude}(thread7)
|-{claude}(thread8)
|-{claude}(thread9)
`-{claude}(thread10)
Process state: Rl+ (Running, multi-threaded, foreground)
Hypothesis
Possible deadlock in the Node.js event loop — likely waiting on an SSE stream from the API with a broken/stalled connection, while the terminal I/O thread is also blocked.
6 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
I'm experiencing the same issue. Here's detailed technical analysis:
## Thread State Analysis
Analyzed frozen processes via
/proc/<pid>/task/*/wchan:| Thread Type | State | Count |
|-------------|-------|-------|
| Main thread |
ep_poll(waiting for epoll events) | 1 || Worker threads |
futex_wait_queue(blocked on mutex) | 18 || I/O thread |
wait_woken| 1 |## Diagnosis
This is a thread deadlock:
ep_poll, waiting for eventsfutex_wait_queue- waiting for a mutexProcess shows
State: R (running)because one thread is active, but the event loopnever runs.
## Concrete Reproduction Trigger
Bash tool execution reliably triggers the freeze. Specific example:
stty -F /dev/ttyUSB0 115200 raw -echo && timeout 8 cat /dev/ttyUSB0 2>&1 || trueHowever, the freeze also occurs with non-blocking commands and background workarounds
(
command &). Any Bash tool execution can trigger it.## Debug Log Analysis
With
--debugflag enabled, the log (~/.claude/debug/) shows:[ToolSearch:optimistic]lines (20+ identical at sametimestamp)
## Additional Evidence
After killing the frozen process with
kill -9:Claude Code
## Key Difference from #19344 (GC Death Spiral)
| Metric | GC Death Spiral (#19344) | This Issue |
|--------|--------------------------|------------|
| CPU | 150-180% | Low (no spinning) |
| Thread state | GC functions | futex_wait_queue |
| Memory | Growing | Stable |
This is NOT a GC issue - it's a mutex deadlock in the Bash tool execution path.
## Environment
## Frequency
Started a few days ago. Occurs irregularly - sometimes every few minutes, sometimes
every few hours. Multiple freezes during a single debugging session.
I am experiencing the same issue. Always happens once Claude code has been running in the same session for quite some time. Fully freezes.
AI Assistant:
Additional data: strace confirms stdin reads succeed but TUI silently drops all input
Reproduced on both v2.1.37 and v2.1.39 — the v2.1.39 fixes ("process hanging after session close", "fatal errors being swallowed") do NOT address this.
Environment
--resume)Reproduction pattern
Both freezes followed the same sequence:
❯prompt renders at the bottom but is non-functionalWhat strace revealed (conclusions)
Ran
strace -p <pid> -e trace=read,write -f -tas root on both stuck processes. Key findings:read()from the terminal PTY — this is the normal stdin-reading state, so the event loop is alive and waiting for input.tmux send-keys, strace showsread(fd, "\33", ...) = 1(one byte read successfully). The TUI does not react at all. Identical result on both v2.1.37 and v2.1.39.read(), but the TUI state machine drops everything.ss -tnp | grep pid=<PID>returns empty. The API connection is completely gone — no outbound sockets at all. Only a few localhost LISTEN sockets remain (v2.1.37) or none (v2.1.39).wait_woken, one thread indo_epoll_wait(event loop), remaining 8–16 threads infutex_do_wait(idle workers), one inwait_woken(inotify). No thread is stuck on I/O, network, or a lock — they're all just sleeping with nothing to do.JSONL conversation file stops being written
The conversation JSONL stops updating at the moment the API call is made. The last recorded entry is always a
tool_result(the response to the last Bash command). The subsequent assistant API response that would follow is never written — consistent with the streaming connection dying before any data arrives.Interpretation
The API streaming connection drops silently (likely HTTP/2 stream reset or TCP timeout not propagated). The Node.js HTTP client doesn't fire an error or timeout event. The TUI state machine is stuck in "waiting for API response" mode. In this mode, it reads stdin bytes but discards them — neither Escape (documented interrupt) nor Ctrl+C work.
The event loop has no pending I/O (no sockets, no timers), so it just sleeps on epoll with nothing to wake it up. The process is effectively a zombie: alive, reading stdin, but unable to process input or make progress. Only
kill -9works.Suggested fix areas
I have full sanitized strace logs,
/procdumps (thread wchans, fd maps, memory stats), and pane captures available if any of these would be helpful for debugging. Happy to share on request.Same bug on macOS ARM64, v2.1.92 (April 2026).
Frozen process had zero TCP connections and was 94% idle in kevent64 — waiting on a dead connection. Happens ~once/day on a university network with dynamic IP. Full write-up: #45269
Hit the same symptom fingerprint on Linux today, but the diagnostic data points at a different mechanism than the SSE hypothesis. Adding it here in case it helps narrow down the class.
Environment
Symptom (identical to OP)
2m 33sindefinitelyRl+state, ignores Escape, Ctrl-C, SIGTERMWhat's different from the SSE hypothesis
The hang happened during a purely local Bash tool call — a Node build piped through
tail, roughlynpm run build 2>&1 | tail -80(foreground, not backgrounded). No network I/O was in flight./procdiagnostics on the hot thread:wchan=0+ emptysyscall= pure-userspace spin, not blocked on I/O. Every other thread was idle:So only the main event-loop thread was spinning — looks like a runaway JS loop (regex catastrophic backtracking or similar in the stdout handler), not a stalled SSE reader.
Likely trigger: orphaned pipe from a zombie subprocess
The build's wrapper bash was a zombie (
Zstate,[bash] <defunct>) — the build had already died over an hour before I killed Claude. Its stdout pipe was apparently still held open by a detached grandchild (Vite spawnsesbuildas a persistent service process), and Claude's parent never processed the close event.Reproduction hypothesis:
$cmd 2>&1 | tail -Nforeground Bash tool$cmdspawns a long-lived detached child that inherits the stdout FD (e.g., Vite'sesbuildservice)Signal-handling note
Symptoms align with Node's signal-through-event-loop model: a userspace-starved main thread can't deliver JS-level signal handlers, so Ctrl-C and SIGTERM both become no-ops. Whatever internal watchdog Claude Code has didn't trigger either — suggesting it also runs on the main loop rather than a worker thread.
Session JSONL survived
Last flush was ~2 minutes after session start; killed 1h47m later. Resume-via-disk works fine; only the in-flight (dead) tool output was lost.
Happy to share the full diagnostic bundle (per-thread
/procstate, 2000-line pane scrollback,top -Hsnapshot, process tree) if it'd be useful.