Infinite CPU loop on --resume: main thread never yields to event loop

Resolved 💬 7 comments Opened Feb 6, 2026 by ashishkf Closed Mar 6, 2026

Bug Description

Claude Code v2.1.33 enters an infinite CPU loop (100% of one core) when resuming a session with --resume. The process becomes completely unresponsive — no user input is accepted, no network I/O occurs, and the conversation file stops being updated. The only remedy is kill.

Environment

  • Version: 2.1.33
  • Platform: macOS 26.1 (Darwin 25.1.0), ARM64 (Apple Silicon)
  • Shell: zsh

Steps to Reproduce

  1. Start a session with tasks, subagents, and tool results (session had 3 tasks, 1 subagent, ~700KB conversation)
  2. Resume it with claude --resume <session-id>
  3. Process launches and immediately pegs CPU at 100%
  4. Terminal is unresponsive — cannot type, Ctrl+C doesn't work cleanly

Reproduced multiple times: killing and restarting with the same session reproduces it. Starting a fresh session (without --resume) in the same project directory works fine. Other Claude Code processes running concurrently on the same machine are responsive.

Configuration Context

  • ~190 plugin skills installed (23 plugin packages from marketplace)
  • 5 custom slash commands, 5 custom skills, 1 custom agent
  • 3 MCP servers configured (1 Docker-based, 1 npm-based, 1 built-in chrome MCP)
  • Pre/Post tool-use hooks configured
  • Project has a settings.local.json with ~25 permission allow entries
  • Project directory contains multiple old conversation files (largest: 53MB)

Diagnosis via sample (macOS CPU profiler)

Four consecutive sample snapshots were taken over ~14 minutes. All show the same pattern:

Main thread (event loop) is 100% CPU executing JIT-compiled JavaScript and never yields to kevent64:

2499/2499 samples (100%) - main thread in JS execution
  2309/2499 (92.4%) - single hot JIT function
    1131/2309 (49%) - iterating over ~40+ elements in address range 0x120d42xxx
    Each leaf address gets 10-45 samples = uniform iteration pattern

The same JIT function (address range 0x120d428180x120d43bf8) appears in all 4 samples, confirming it's a stable compiled function stuck in a loop, not transient compilation.

Timeline of degradation:

| Sample | Time | Main Thread | Network I/O | Conv File |
|--------|------|-------------|-------------|-----------|
| #1 | 22:04 | 100% JS | Active | Growing |
| #2 | 22:08 | 79% idle (GC pause) | Active | Growing |
| #3 | 22:11 | 100% JS | Active | Growing |
| #4 | 22:18 | 100% JS | Zero bytes | Stopped |

Memory footprint oscillated: 1.0G → 414M (GC) → 1.4G → 1.4G, peaking at 1.5G.

All worker threads (12× Bun Pool, Heap Helpers, JIT Worklist, HTTP Client, File Watcher) are properly idle/waiting — only the main thread is stuck.

Key observation: By sample #4, nettop shows identical byte counts across 2-second intervals — the process has stopped all network I/O while still burning 100% CPU. The conversation JSONL file also stopped being written. The process is doing no useful work.

Additional lsof / ps Data

PID 64712  99.9% CPU  1.5GB RSS  state=R+  time=16:21
- 4 TCP connections to Anthropic API (ESTABLISHED but idle)
- 1 TCP to GCP, 1 to AWS (MCP servers)
- 24 unix domain sockets (MCP stdio pipes)
- 86 total file descriptors
- Child processes: context7 MCP, docker MCP, chrome MCP, pyright, typescript-language-server, gopls (all idle, 0% CPU)

Sample Files

<details>
<summary>Sample #4 (22:18) - Sort by top of stack</summary>

Sort by top of stack, same collapsed (when >= 5):
        __ulock_wait2  (in libsystem_kernel.dylib)        29988
        __psynch_cvwait  (in libsystem_kernel.dylib)        14957
        mach_msg2_trap  (in libsystem_kernel.dylib)        2501
        __workq_kernreturn  (in libsystem_kernel.dylib)        2499
        kevent  (in libsystem_kernel.dylib)        2499
        kevent64  (in libsystem_kernel.dylib)        2499
        ???  (in <unknown binary>)  [0x1211abb90]        132
        ???  (in <unknown binary>)  [0x120d42cf4]        45
        DYLD-STUB$$pthread_getspecific  (in 2.1.33)        34
        ???  (in 2.1.33)  load address 0x102170000 + 0x16cdf7c        30
        _platform_memmove  (in libsystem_platform.dylib)        30
        ???  (in <unknown binary>)  [0x120d42cd4]        29
        ???  (in <unknown binary>)  [0x1211ab9e4]        26
        ???  (in <unknown binary>)  [0x120d42cb4]        24
        ???  (in <unknown binary>)  [0x120d43bf8]        24

</details>

<details>
<summary>Sample #4 (22:18) - Main thread call graph (top)</summary>

2499 Thread_27819082   DispatchQueue_1: com.apple.main-thread  (serial)
+ 2499 start  (in dyld) + 7184
+   2499 ???  (in 2.1.33)  load address 0x102170000 + 0x3f90
+     2499 ???  (in 2.1.33)  load address 0x102170000 + 0x536c
+       2499 ???  (in 2.1.33)  load address 0x102170000 + 0x26a430
+         2499 ???  (in 2.1.33)  load address 0x102170000 + 0x1121cd0
+           2499 ???  (in 2.1.33)  load address 0x102170000 + 0x2ab770
+             2499 ???  (in 2.1.33)  load address 0x102170000 + 0x4367bc
+               2499 ???  (in 2.1.33)  load address 0x102170000 + 0x13445c0
+                 2499 ???  (in 2.1.33)  load address 0x102170000 + 0x20b6aec
+                   2499 ???  (in 2.1.33)  load address 0x102170000 + 0x2ee8db4
+                     2499 ???  (in <unknown binary>)  [JIT code]
+                       ... deep JIT call chain (never yields) ...
+                         2309 ???  (in <unknown binary>)  [hot iterative function]
+                           1131 ??? [0x1211ab88c] → 40+ leaf iterations in 0x120d42xxx

</details>

Expected Behavior

claude --resume should load the session and present an interactive prompt within a few seconds.

Actual Behavior

Process immediately enters 100% CPU infinite loop in JIT-compiled JavaScript. Never becomes interactive. Must be killed externally.

🤖 Generated with Claude Code

View original on GitHub ↗

This issue has 7 comments on GitHub. Read the full discussion on GitHub ↗