VS Code Extension 2.1.204 hangs for 90+ seconds every 30-40 min (macOS ARM64) — native process correctly idle in kevent64
Bug Report: Claude Code VS Code Extension Hangs After 30-40 Minutes (macOS ARM64)
Summary
Claude Code VS Code extension reproducibly hangs/freezes for 90+ seconds every 30-40 minutes of use, with the native claude subprocess correctly idling in kernel wait (kevent64). The hang occurs across multiple different projects, not specific to any single codebase. The extension and IDE remain responsive—the freeze appears upstream in the extension host's IPC/event-loop layer.
Environment
- Extension version: 2.1.204 (build tag:
cc_version=2.1.204.d9b) - Internal build path:
~/.vscode/extensions/anthropic.claude-code-2.1.204-darwin-arm64 - macOS: 26.5.1 (build 25F80)
- Hardware: Apple Silicon (Mac16,10, ARM64), 16GB RAM, 10 CPU cores
- Standalone CLI version: 2.1.85 (separate install)
Symptom
Single VS Code window with single Claude Code tab hangs for 90+ seconds, blocking the chat panel from responding. Then resumes cleanly with no restart or state loss. Occurs repeatedly across multiple projects and multiple sessions over a period of weeks.
Typical hang sequence:
- User working normally for ~30-40 minutes
- Claude Code UI freezes (chat panel unresponsive, webview spinner halts)
- Native log file shows 90-96 seconds of complete silence between log messages
- System remains responsive (not OS-level freeze)
- Extension spontaneously resumes without user intervention
- No error messages logged before or after the freeze
Forensic Evidence
1. Extension Log Silence
The Claude VSCode extension's own debug log (~/Library/Application Support/Code/logs/<timestamp>/window*/exthost/Anthropic.claude-code/Claude VSCode.log) contains a genuine 599-second gap of complete silence between two routine, unrelated update_session_state webview messages. No errors logged before or after the freeze.
2. VS Code Watchdog Did NOT Fire
VS Code's built-in extension host unresponsiveness detector (fires when one extension blocks the shared Node.js event loop for ~10+ seconds) never triggered. This rules out the classic "another extension is hogging the shared event loop" scenario.
3. Native Process Stack Sampling (5 Independent Captures)
A background watchdog monitoring the extension's own log file for silence detected and captured five separate hangs (silence durations 92s, 96s, 96s, 96s, and 96s, across a ~90 minute window) using macOS's sample(1) tool. Stack traces from all five show the identical pattern:
Main thread behavior (~95-98% of samples):
- Thread:
DispatchQueue_1: com.apple.main-thread(serial queue) - All samples stack at:
kevent64inlibsystem_kernel.dylib - This is a legitimate blocking kernel wait, not a busy-loop or spin
- Conclusion: The native
claudebinary is correctly idle, waiting for I/O/events
Recurring side-branch (~2-6% of samples, single-digit to ~90 count):
- Appears at nearly identical binary offsets across all five independent captures, taken minutes to tens of minutes apart
- Example offsets:
+0x75fdac→+0x275a584→+0x278e7fc→+0x277dce8 - This suggests a specific periodic callback/timer that runs consistently during the freeze
- The work done by this branch does NOT wake/resolve the main response path
- Binary is stripped (no symbols), so function identity unknown, but pattern is consistent
4. Memory Footprint Normal
Physical memory footprint of claude process during all five hangs:
- Hang 1: 201.0 MB (peak 216.0 MB)
- Hang 2: 201.1 MB (peak 216.0 MB)
- Hang 3: 278.6 MB (peak 293.1 MB)
- Hang 4: 173.3 MB (peak 191.3 MB)
- Hang 5: 211.0 MB (peak 226.0 MB)
- System-wide memory pressure was not critically high during these hangs
This rules out memory bloat or OOM-adjacent behavior in the native process as the cause of these hangs.
5. Capture Files
Raw forensic data (stack dumps + memory/CPU snapshots) for all five hangs is attached as a gist:
https://gist.github.com/terrancedjones/6f4bb89b7e298ec65109d0ae17e6af5e
Each file contains: full sample(1) output, vm_stat, sysctl vm.swapusage, and ps aux sorted by memory for the time window.
Root Cause Analysis
The evidence points away from the native binary itself and toward the extension host's IPC/event-loop layer:
- Native
claudesubprocess is legitimately waiting (kevent64) for events/input - Memory footprint is normal (not leaking)
- The periodic side-branch suggests some timer/callback is running, but it's not waking the stalled wait
- This indicates the extension host's TypeScript/JS code or the webview (chat panel UI) renderer is not feeding events to the native process when it should be
The hang is likely caused by:
- A deadlock or event-loop stall in the extension host between the webview and the native subprocess's stdio/IPC channel
- A missing wakeup signal after a specific operation
- A resource contention issue (file lock, pipe buffer, etc.) in the IPC layer
- A timer/polling mechanism that's checking for input but not actually reading it
Steps to Reproduce
Difficult to reproduce on demand, but consistent over weeks:
- Open Claude Code VS Code extension
- Work normally in a single tab for ~30-40 minutes
- Observe: chat panel freezes, extension log shows 90+ second silence
- Wait ~5 minutes: extension resumes without action
Workarounds (Known)
- No intervention needed — all 3 captured hangs self-resolved within ~90-100 seconds with no restart, crash, or lost session state (confirmed directly from the watchdog's "log activity resumed" timestamps)
- Reloading the VS Code window is not required to recover, though a user who doesn't know it will self-resolve may reasonably reach for it out of frustration
Related Known Issues
This may be related to or a variant of:
- Issue #30417 (VS Code Extension hangs indefinitely on macOS ARM64)
- Issue #25976 (Dual process spawn with MCP server errors)
- Issue #39381 ("Not responding - try stopping" with no recovery mechanism)
Suggested Next Steps for Maintainers
- Check the extension host's stdio/pipe buffer handling during idle periods
- Review event-loop wake conditions between the webview renderer and native subprocess IPC
- Add explicit timeout/heartbeat detection to the extension's native process communication layer
- Profile the ~2-6% recurring side-branch function using non-stripped binaries to identify the periodic callback
- Consider whether
kevent64is the right wait primitive or if there's a race condition in how events are polled
Additional Context
- This is not a single-project issue (happens across PropertyHunter-Go, PropertyHunter-React, and other repositories)
- This is not a memory pressure issue (system was healthy during the hangs)
- This is not a CLI issue (the CLI was updated to 2.1.85 but the extension hangs persist at 2.1.204)
This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗