v2.1.23+ causes 100% CPU hang with multiple parallel instances and hooks
Status Fixed / completed
Reported on v2.1.27
Maintainer reply None cached
Workaround ✓ Mentioned in thread ↓
Activity 9 comments · opened Jan 31, 2026 · closed Aug 19, 2026
Description
Claude Code hangs with 100% CPU usage when running multiple parallel instances with hooks enabled. This regression was introduced somewhere between v2.1.22 and v2.1.23.
Environment
- OS: Linux (WSL2, Ubuntu)
- Claude Code version: 2.1.27 (also affects 2.1.25)
- Installation: Native client (not npm)
- Profile: Custom config directory via
CLAUDE_CONFIG_DIR
Steps to Reproduce
- Enable hooks in settings (
disableAllHooks: false) - Have multiple plugins with hooks enabled (e.g., PreToolUse hooks for Bash, Write, Edit)
- Start 2+ Claude Code instances in parallel
- One or more instances will hang at 100% CPU
Expected Behavior
Multiple parallel instances should work without hanging, as they did in v2.1.22.
Actual Behavior
- Instances hang with ~100% CPU usage
- Even simple commands like
/plugincause hangs - The UI becomes unresponsive
- Process must be killed with
kill -9
Workaround
Using v2.1.22 resolves the issue completely:
CLAUDE_CONFIG_DIR=$HOME/.claude-work /path/to/versions/2.1.22
With v2.1.22, everything works perfectly - all hooks, all plugins, multiple parallel instances.
Potentially Related Changes
Looking at the changelog, these changes between 2.1.22 and 2.1.27 might be relevant:
- v2.1.27: "Content-level
asknow takes precedence over tool-levelallow" - permission handling change - v2.1.23: "Fixed race condition causing 400 errors with prompt caching scope" - might have introduced new race conditions
- v2.1.23: "Fixed per-user temp directory isolation on shared systems"
Hook Configuration
The hooks are standard PreToolUse/PostToolUse hooks that return JSON with permissionDecision. Example hook output:
{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow"}}
Additional Context
- The issue does NOT occur with v2.1.22 regardless how many sessions in parallel and regardless which hooks are enabled or disabled
- CPU usage stays at around 90-100% until the process is manually killed
- No error messages are displayed before the hang
- The issue does occur on the first user prompt then it hangs completely
Showing cached comments. Read the full discussion on GitHub ↗
8 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Correction: Disabling hooks (
disableAllHooks: true) does NOT fix the issue. The only confirmed workaround is downgrading to v2.1.22.This makes the issue more similar to #22158 - it appears to be a fundamental problem in v2.1.23+ rather than hook-specific.
It's still present in .29, and feels different than the .27 crashes from yesterday. It was hanging on pretooluse for me, but only on certain calls.
Subscribing - experiencing similar issues
same problems for me
I run Claude Code on WSL2 with 8 hooks (via
npx cc-safe-setup) and haven't hit this CPU hang — but I typically run 1 instance, not multiple in parallel.Possible workaround for parallel instances:
Ensure hooks use file locks to avoid concurrent execution conflicts:
Alternative — reduce hook execution for parallel sessions:
Check if the hook is being called too frequently by logging timestamps:
The 100% CPU pattern suggests hooks are being spawned in a tight loop. File locking prevents the cascade.
Adding macOS Apple Silicon evidence + quantitative scope to this thread, since this issue is framed Linux-WSL2 only but the failure mode appears identical on macOS.
I filed #55609 earlier today for what I now believe is the same bug: 100% CPU hang on hook-configured
claudeafter backgrounded-bash interrupt. The bot suggested this issue as a duplicate, and reading your repro, I agree.Two corrections vs the framing here:
claudesession with any hook in~/.claude/settings.json(SessionStart / SessionEnd / Stop / PreToolUse / PostToolUse) freezes on backgrounded-bash interrupt. ~60 second repro.fork()calls system-wide). Not just process-stuck, system-stuck.Quantitative scope from a freeze-capture monitor I had running this morning (08:32–12:05 PDT, ~3.5 hours active dev):
fork: retry: Resource temporarily unavailablerepeatedly while trying to spawnsample/vm_stat— kernel was system-wide out of process slots, not just claude stuckStack trace from one stuck claude (PID 77747, 2026-05-02 08:27:44, claude 2.1.126, macOS 26.4.1):
com.apple.main-thread(serial)+ 0x6569a0 → 0xe37c6c → 0x849910 → ...gcoredisassembly in #18532 — V8 JIT property-descriptor-hash-table loopI haven't downgraded to v2.1.22 yet but will test if it would help diagnosis. Also worth noting: the bot also flagged #52253 ("tree-kill dependency causes pgrep storm / 100% CPU when reaping Bash subprocess trees on macOS") as a duplicate — the
tree-kill/pgrepangle in that title matches my stack trace exactly. Could be the same root cause as the regression introduced in 2.1.23.Forensic dir (7 freeze snapshots, 21-event log, sample profiles for 5 PIDs, vm_stat captures, fork-failure stdout) ready to share. Disclosure: I build AgentOps on top of Claude Code; filing as a daily user.
Confirming this regression still reproduces on macOS in 2.1.126 (originally filed for Linux/WSL2 — bug is platform-agnostic). 4-step repro in #55609 triggers it deterministically; vanilla
settings.json({}) does not.System spindump caught the parent main-thread in a
posix_spawnloop with kernel turnstile waits namingpgrepchildren — thetree-kill/Bg6storm tracked in #52253. Forensic detail: #52253 comment.