Skip to content

[BUG] Claude code wsl2 freeze issue #27367

Description

@GangsubLim

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet
  • This is a single bug report (please file separate reports for different bugs)
  • I am using the latest version of Claude Code

What's Wrong?

Claude Code on WSL2 freezes for 20-40 seconds in specific situations:

  • Startup — TUI takes 20-40s to become responsive after launch (7+ repeated calls)
  • After exiting commands — e.g. pressing Esc to back out of /plugin, /model, etc. (~2-3s, single call)
  • On /exit — ~2-3s hang before session closes (single call)

The root cause is repeated uncached powershell.exe invocations to resolve $env:USERPROFILE. Each PowerShell cold start takes ~2.5s due to .NET runtime and profile loading, and this is called 7+ times without caching the result.

This provides the strace-level root cause analysis that was missing from previous reports of the same issue:

Root Cause Analysis

1. System diagnostics ruled out common WSL2 issues:

Check Result
DNS resolution 0.005s ✅
API connectivity (curl) 0.26s total ✅
Memory/swap 897/15909MB, 0 swap ✅
I/O wait 0% ✅
CPU 100% idle ✅

2. strace reveals repeated interop calls with 2.5-4.4s gaps:

sudo strace -p $(pgrep claude) -T -tt -e trace=network,read,write
17:08:30.838093 recvfrom(24, ...) = -1 EAGAIN           ← wait starts
                                                          ← ⏳ 2.7s blocked
17:08:33.558024 recvfrom(22, "C:\\Users\\<username>\r\n", ...)  ← Windows path received

Each cycle:

  1. socketpair() × 2 — pipes for child process
  2. recvfrom()EAGAIN — blocked 2-4s waiting for child
  3. recvfrom()"C:\\Users\\<username>" — Windows home path
  4. SIGCHLD — child process exits
  5. recvfrom()"/mnt/c/Users/<username>" — wslpath result
  6. read() → config data
  7. Repeat from step 1 (no caching)

3. strace -f -e trace=execve identifies the exact command:

[pid 9529] execve("/mnt/c/WINDOWS/System32/WindowsPowerShell/v1.0//powershell.exe",
    ["powershell.exe", "-Command", "$env:USERPROFILE"], ...) = 0

Timing:

17:11:21.756804  execve(powershell.exe)   ← start
17:11:24.272804  exited with 0            ← 2.5s later

4. This repeats 7+ times in 30 seconds with identical results:

Gap start Gap end Duration Result (always identical)
30.838 33.558 2.7s C:\Users\<username>
34.530 36.959 2.4s C:\Users\<username>
37.992 40.685 2.7s C:\Users\<username>
41.710 44.245 2.5s C:\Users\<username>
45.266 48.141 2.9s C:\Users\<username>
49.159 53.598 4.4s C:\Users\<username>
54.642 57.265 2.6s C:\Users\<username>

7 calls × ~2.7s avg = ~19s of freeze in 30 seconds.

The Problem

  1. No caching — result is always identical but never cached
  2. PowerShell is the heaviest optioncmd.exe /c echo %USERPROFILE% is ~0.3s; environment variable reads are instant
  3. Repeats on every state transition — startup, exiting menus, termination all trigger fresh calls

Suggested Fix

The core issue is lack of caching, not the choice of PowerShell itself. The same immutable value is fetched 7+ times per session.

  1. Cache the result after the first callUSERPROFILE doesn't change during a session. Call once, store, reuse. This alone eliminates the problem regardless of how the value is fetched.
  2. Read from environment variables directly — WSL already exposes Windows environment info (e.g. WSLENV, /proc/*/environ), which would avoid interop entirely.
  3. If interop is required, use a lighter methodcmd.exe /c echo %USERPROFILE% (~0.3s) or wslvar USERPROFILE from wslu are significantly faster than PowerShell.
  4. If PowerShell must be used, add -NoProfile — profile loading accounts for most of the ~2.5s overhead. powershell.exe -NoProfile -Command "$env:USERPROFILE" would be much faster.

Current Workaround

A shell shim at ~/bin/powershell.exe that intercepts the $env:USERPROFILE query:

#!/bin/bash
for arg in "$@"; do
    if [[ "$arg" == '$env:USERPROFILE' ]]; then
        echo "C:\Users\"
        exit 0
    fi
done
exec /mnt/c/WINDOWS/System32/WindowsPowerShell/v1.0/powershell.exe "$@"

With export PATH="$HOME/bin:$PATH" in ~/.bashrc, this eliminates the freeze entirely.

What Should Happen?

Claude Code should resolve $env:USERPROFILE once and cache the result, or use a lighter-weight method (environment variable, cmd.exe). Startup, command transitions, and exit should complete without noticeable delay on WSL2.

Error Messages/Logs

Steps to Reproduce

  1. Install Claude Code natively on WSL2 (Ubuntu)
  2. Run claude
  3. Observe 20-40 second freeze during startup before TUI becomes responsive
  4. After TUI loads, run /plugin and press Esc to back out — ~2-3s freeze (single call)
  5. Run /exit — ~2-3s delay before terminating (single interop call)
  6. Verify with sudo strace -f -tt -T -e trace=execve -p $(pgrep claude) — repeated powershell.exe -Command "$env:USERPROFILE" calls visible during each freeze

Note: The severity of the freeze depends on each system's PowerShell cold start time. Our environment reports ~2.5s per call (profile loading alone: ~2492ms). Systems with lighter PowerShell profiles may experience shorter delays, but the unnecessary repeated calls remain inefficient regardless. You can check your PowerShell load time with: time powershell.exe -Command '$env:USERPROFILE'

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

No response

Claude Code Version

2.1.50 (Claude Code)

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

WSL (Windows Subsystem for Linux)

Additional Information

  • Operating System: Windows 11 + WSL2 (Ubuntu 24.04)
  • CPU: Intel i5-13600KF
  • RAM: 16GB allocated to WSL2
  • Installation: Clean install, no plugins or extensions
  • PowerShell profile load time: ~2500ms (reported by PowerShell itself)
  • This affects all Claude Code WSL2 users — the interop overhead is inherent to WSL2's Hyper-V architecture
  • Severity scales with PowerShell profile complexity and Windows system load

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions