Hook process freezes at startup on Windows (thread Suspended, 0 CPU, never resumed) -> hangs the turn; kills subagents permanently

Open 💬 0 comments Opened Jul 15, 2026 by MokebeGluszak

Hook process freezes at startup on Windows (thread Suspended, 0 CPU, never resumed) → hangs the turn; kills subagents permanently

Environment

  • Claude Code: 2.1.210
  • OS: Windows 11 Pro (26200)
  • Shell: PowerShell + Git Bash
  • Configured hooks: PreToolUse, PostToolUse, Stop, SubagentStop, UserPromptSubmit (Python scripts)

Summary

A hook child process (python.exe) is spawned but never runs its first instruction — its
main thread stays in the kernel Suspended wait state (suspend_count = 1, exactly zero CPU
time
). Claude Code waits for the hook, logs timed out — output discarded, but neither
resumes nor kills the process
, so the turn hangs. Intermittent, Windows-specific.

For the main session this manifests as a turn hanging 30–60 min. For subagents it is worse:
the subagent's turn is abandoned, the tool never returns a tool_result, and the subagent dies
permanently — the parent session spins forever with a result that will never arrive.

Evidence (measured, not guessed)

Frozen hook process, characterised with a debugger:

  • main thread WaitReason = Suspended, suspend_count = 1
  • exactly 0 ms CPU (control: a process that started normally and then blocked on stdin always

shows 15–31 ms, 12/12 — so 0 ms means it never executed a single instruction)

  • survives its 2–3 s timeout budget indefinitely (observed 46–127 min)
  • a single ResumeThread() (previous suspend_count = 1) → the process finishes and exits in <1 s.

Reproduced 5×.

  • 120 spawns of the same hook without Claude Code → zero freezes (31 ms each) → not the script.
  • CC waits for such a hook and hangs the whole turn — including on a plain Read, not only shell.

Subagent impact, measured across 194 subagent runs (one week):

  • 7 subagents died (3.6%) — transcript ends mid-tool_use (a tool was requested, tool_result

never arrived), no further lines for 89–173 min while the parent session was still alive.

  • Two deaths fall inside a hook-freeze window recorded independently in our watchdog log.
  • Correlates in time: subagent deaths start the same day the hook-freeze log starts.
  • Not model/variant related: dies on both Opus and Haiku subagents; last tool before death is a

plain Read/Grep/WebFetch with no pattern.

Ruled out (in case it helps narrow it)

  • Not the hook script (120 spawns outside CC → 0 freezes).
  • Not antivirus alone (no Defender events for python.exe; spawn timing stable ~65 ms when it works).
  • A libuv uv_spawn CREATE_SUSPENDED race was our first hypothesis and we DISPROVED it in

libuv/src/win/process.c: CREATE_SUSPENDED is set only for UV_PROCESS_DETACHED, and the
job-object assignment sits in a mutually-exclusive branch. Hooks are not detached, so that path
does not apply. Mechanism remains unknown — we did not want to ship you a guessed cause.

Why this matters / severity

  • Any user with hooks is exposed on every tool call (we run several synchronous hooks per tool → a

few hundred process spawns per subagent run). A user with zero hooks never hits it, which likely
explains why it is rarely reported.

  • The subagent case is silent data loss: work is lost, the session spins forever, and there is **no

timeout and no error** surfaced to the parent — the Agent tool never returns and never fails.

Two concrete asks for the platform

  1. A timeout/abort on a hung hook: if a hook exceeds its budget, CC should resume-or-kill the

process (a single ResumeThread demonstrably unblocks it) instead of waiting indefinitely.

  1. A subagent that loses its turn to a hung hook should fail the Agent tool (or retry), not leave

the parent spinning with no result and no error.

Our current workaround (in case useful as a reference)

A watchdog that scans for python.exe hook processes from our hooks dir with 0 CPU and age past a
grace window, and calls ResumeThread() on the suspended thread. The turn unfreezes in ~3–5 s. This
is a symptom mitigation; the root cause is inside CC's hook-spawn path on Windows.

Repro (best-effort — it is intermittent)

  1. Windows, several synchronous hooks registered per tool event (Python).
  2. Drive tool-heavy work, especially subagents (30–70 tool calls each → hundreds of hook spawns).
  3. Occasionally a hook python.exe will sit at suspend_count=1, 0 CPU; the turn hangs. For a

subagent, the run never returns.

View original on GitHub ↗