[BUG] Bash tool: all commands fail with Bad file descriptor on Windows (Git Bash stdout broken)
Bug Description
Every command run through the Bash tool fails with exit code 1. Stdout file descriptor (fd 1) is broken - bash cannot write any output. PowerShell commands work fine through the same tool.
This is not the same issue as #18469 (which was silent empty stdout with exit code 0). This produces an explicit Bad file descriptor error on fd 1.
Environment
- Claude Code version: 2.1.45
- Platform: Windows 11 (MINGW64_NT-10.0-26200 3.6.4-b9f03e96.x86_64)
- Shell: Git Bash (C:\Program Files\Git\usr\bin\bash.exe)
- Sandbox: Disabled (sandbox.enabled: false)
- No CLAUDE_CODE_SHELL or CLAUDE_CODE_GIT_BASH_PATH env vars set
Reproduction
Any bash command fails:
Bash(date) -> Exit code 1 (no output)
Bash(echo hello) -> Exit code 1 (no output)
Bash(pwd) -> Exit code 1 (no output)
Bash(env | sort) -> Exit code 2 (no output)
PowerShell wrapper works fine:
Bash(powershell -Command Get-Date) -> Tuesday, February 17, 2026 3:46:15 PM
Root Cause (diagnosed)
Running bash directly via PowerShell with stderr captured reveals the error:
powershell
& 'C:\Program Files\Git\bin\bash.exe' -c 'echo hello' 2>&1
Output:
/usr/bin/bash: line 1: echo: write error: Bad file descriptor
The stdout pipe that Claude Code creates for capturing bash output is not valid from MSYS2/Git Bash's perspective. Bash builtins (echo, pwd) fail because fd 1 is broken. PowerShell works because it handles Windows pipe handles natively.
Diagnostic Steps Taken
- Confirmed PATH is correct - C:\Program Files\Git\usr\bin is on PATH, bash binary exists and runs
- Removed ~/.bashrc - no change, still broken (rules out #18469 root cause)
- Checked system bashrc/profile - standard Git for Windows defaults, nothing unusual
- No CLAUDE env vars - CLAUDE_CODE_SHELL and CLAUDE_CODE_GIT_BASH_PATH are not set
- Git Bash works normally outside of Claude Code (user runs it daily)
Expected Behavior
Bash commands should execute and return stdout, as they do in a normal Git Bash terminal.
Likely Cause
The child process spawning mechanism is not passing stdout pipe handles in a way that MSYS2's POSIX fd layer can use. This may be related to how child_process.spawn() or similar Node.js APIs create pipes on Windows - the Windows HANDLEs are not being translated to valid POSIX file descriptors by MSYS2's crt0 initialization.
Related Issues
- #18469 - Bash tool doesn't capture stdout from shell scripts on Windows (different symptoms: silent empty stdout, exit 0; fixed in v2.1.27)
- #20453 - CLAUDE_CODE_SHELL not respected on Windows (closed as dup)
- #20034 - Hook stdout routed to stderr in Git Bash (closed as dup of #18469)
- #25558 - CLAUDE_CODE_SHELL ignored on Windows (open)
This issue has 11 comments on GitHub. Read the full discussion on GitHub ↗