[BUG] Bash tool crashes with EEXIST when session-env folder already exists (mkdir missing recursive: true)

Resolved 💬 3 comments Opened May 9, 2026 by goldenbutter Closed May 13, 2026

Preflight Checklist

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

What's Wrong?

The Claude Code Bash tool crashes intermittently mid-session with the following error:

EEXIST: file already exists, mkdir 'C:\Users\<user>\.claude\session-env\<session-id>'

The <session-id> in the error message matches the current session's ID — meaning the host process is calling mkdir on a folder it already created earlier in the same session, without { recursive: true } and without an existence check.

This is the same bug class that previously crashed Stop hooks (forced disable of the ralph-loop plugin) and PreToolUse:Edit/Write hooks (forced disable of the security-guidance plugin) in this environment over the last 36 hours. A single shared code path in the host appears to call bare mkdirSync(path) on the session-env folder without idempotency, and Bash tool execution + hook execution both go through it.

In one 14-hour session on 2026-05-08 (vanilla HTML prototype build, no npm/node steps), the bug fired 8-10 separate times during routine Bash calls (git log, grep, wc, curl, magick). It blocked image-cropping work entirely; manual fallback to external tooling was required.

A side effect of the bug: ~/.claude/session-env/ accumulates orphaned per-session folders indefinitely — 258 folders dating back to 2026-04-10 in this environment, almost all empty. There is no apparent cleanup on session end.

What Should Happen?

The Bash tool should be able to invoke commands repeatedly within a single session without crashing on its own session-env folder.

Specifically:

  1. Folder creation must be idempotent. Replace bare mkdirSync(path) with mkdirSync(path, { recursive: true }), or guard with if (!existsSync(path)) mkdirSync(path).
  2. The session's folder should be cleaned up on graceful shutdown, plus a startup sweep of folders older than e.g. 24 hours, to prevent indefinite accumulation in ~/.claude/session-env/.

Error Messages/Logs

EEXIST: file already exists, mkdir 'C:\Users\<user>\.claude\session-env\<session-id>'

Steps to Reproduce

  1. Start a Claude Code session on Windows 11 (PowerShell or Git Bash as host shell, hosted inside VS Code integrated terminal).
  2. Run several Bash tool calls in succession during the same session — anything routine works: echo hello, git log --oneline -5, wc -l <file>, grep <pattern> <file>.
  3. After several Bash calls within the same session (frequency varies; observed 8-10 times in a 14-hour session), a subsequent Bash call returns:

EEXIST: file already exists, mkdir 'C:\Users\<user>\.claude\session-env\<session-id>'
The <session-id> in the error matches the current session's ID — i.e. the host is mkdir-ing a folder it created earlier in the same session.

  1. Recovery (workaround): from PowerShell (outside the dead Bash tool), run:

Remove-Item 'C:\Users\<user>\.claude\session-env\<session-id>' -Recurse -Force
The next Bash tool call succeeds. The bug recurs after a few more calls.

The bug fires for routine commands; no special syntax, environment variables, or filesystem operations are required to trigger it. It is non-deterministic in timing within a session but reliably recurrent across long sessions.

Claude Model

Opus

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.1.138 (Claude Code)

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

VS Code integrated terminal

Additional Information

Related incidents in the same environment (cross-surface evidence)

The same EEXIST mkdir 'session-env\<id>' symptom has appeared on three Claude Code surfaces in this user's environment over ~36 hours:

| Date | Surface | User-visible action |
|---|---|---|
| 2026-05-08 | Stop hooks (ralph-loop plugin) | Plugin uninstalled |
| 2026-05-09 | PreToolUse:Edit/Write hooks (security-guidance plugin) | Plugin disabled |
| 2026-05-08 → 2026-05-09 | Bash tool itself | No fix available, manual recovery only |

This strongly suggests a single shared code path used by Bash tool execution and hook execution — a fix in one place likely resolves all three surfaces.

Environment details

  • Windows 11 Pro 10.0.26200
  • PowerShell 5.1 (host shell)
  • Git Bash (MSYS2) at /usr/bin/bash 5.2.37 (Bash tool runtime)
  • Node.js v24.14.0
  • Settings: defaultShell: powershell, CLAUDE_CODE_USE_POWERSHELL_TOOL=1 (PowerShell tool path is unaffected by this bug — used as the recovery channel)

Side effect: directory leak

~/.claude/session-env/ accumulated 258 orphaned per-session folders dating back to 2026-04-10 before manual cleanup. No graceful or startup cleanup observed.

Suggested fix (one line)

Replace
fs.mkdirSync(sessionEnvPath);

With
fs.mkdirSync(sessionEnvPath, { recursive: true });

View original on GitHub ↗

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