Bash tool fails with exit code 1 on Windows - stdout capture broken

Status Open
Reported on v2.1.45
Maintainer reply None cached
Activity 7 comments · opened Feb 18, 2026

Description

All Bash tool commands that produce stdout output fail with exit code 1 on Windows. Commands that produce no output (like true) succeed. Writing to files works correctly.

Environment

  • Claude Code version: 2.1.45
  • OS: Windows 11 Pro for Workstations (10.0.26100)
  • Shell: Git Bash (MINGW64), GNU bash 5.2.37(1)-release (x86_64-pc-msys)
  • Platform: MINGW64_NT-10.0-26100, x86_64

Steps to Reproduce

  1. Launch Claude Code on Windows with Git Bash
  2. Ask Claude to run any command that produces stdout output

Observed Behavior

| Command | Result |
|---------|--------|
| true | exit 0 ✅ |
| echo "test" | exit 1 ❌ |
| pwd | exit 1 ❌ |
| ls | exit 1 ❌ |
| builtin echo "test" | exit 1 ❌ |
| echo "test" > /tmp/file.txt 2>&1; true | exit 0 ✅ (file contains "test") |

Terminal shows: /usr/bin/echo: /usr/bin/echo: cannot execute binary file

Diagnostics

  • /usr/bin/echo.exe is a valid Windows binary: PE32+ executable for MS Windows 5.02 (console), x86-64
  • /usr/bin/ls.exe is also a valid PE32+ executable
  • Bash builtins work when output is redirected to a file
  • The issue appears to be with stdout capture by Claude Code, not with the binaries themselves
  • MSYSTEM=MINGW64, TERM=xterm-256color

What I've Tried

  • Setting $env:SHELL to various Git Bash paths (C:\Program Files\Git\bin\bash.exe, C:\Program Files\Git\usr\bin\bash.exe)
  • Deleting ~/.claude/shell-snapshots/
  • Reinstalling Git for Windows
  • Updating Claude Code to latest version (2.1.45)
  • Running from different terminals (PowerShell, CMD, Git Bash)
  • Setting $env:SHELL = "powershell" (Claude Code still uses bash)

Expected Behavior

Bash commands should execute and their stdout output should be captured and returned to the agent.

View original on GitHub ↗

7 Comments

github-actions[bot] · 6 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/26413
  2. https://github.com/anthropics/claude-code/issues/26540
  3. https://github.com/anthropics/claude-code/issues/26486

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

tokoba · 6 months ago

Windows 11
Git bash
environment

claude install 2.1.36 claude

----

I believe 2.1.45 is super buggy crap trash. I spend some time investigating however I endup rolling back to stable version.
I will never use claude update again.

KatayR · 6 months ago

Bash commands keep returning "Error: Exit code 1" after the standalone Claude installation.

`
● Bash(pwd 2>&1)
⎿ Error: Exit code 1

● Bash(/bin/pwd 2>&1; echo "EXIT: $?")
⎿ Error: Exit code 1

● Bash(echo "hello world")
⎿ Error: Exit code 1

● Bash(whoami)
⎿ Error: Exit code 1
● Bash(echo "hello") ⎿ Error: Exit code 1 `

Only this works:
● Bash(true)
⎿ (No output)

I'm on windows, Claude Code version is 2.1.45.

Bash works fine outside of Claude Code.

chablitzel · 6 months ago

Edit: Found the likely culprit in the 2.1.45 changelog:

"Improved memory usage for shell commands that produce large output -- RSS no longer grows unboundedly with command output size" This is the change that broke stdout capture on MINGW64. The new streaming/chunked pipe mechanism used to cap memory usage isn't compatible with MSYS2's POSIX fd-to-Win32-handle translation layer. Before 2.1.45, stdout was buffered fully in memory (worked with MSYS2, but leaked on large output). The new approach fixes the memory leak but breaks MSYS2 compatibility.

Root Cause Analysis

I've been debugging this as a user on the same setup (Windows 11, Git Bash MINGW64, CC 2.1.45). Here's what the evidence points to:

The Pattern

The key observation from the issue is:

| Command | Produces stdout? | Result |
|---|---|---|
| true | No | exit 0 |
| echo "test" | Yes | exit 1 |
| builtin echo "test" | Yes (builtin) | exit 1 |
| echo "test" > /tmp/file.txt 2>&1; true | No (redirected) | exit 0, file has content |

Two Separate Failures

1. External MSYS2 binaries can't execute in the CC subprocess

The error /usr/bin/echo: /usr/bin/echo: cannot execute binary file shows that external commands in /usr/bin/ (like ls, pwd, echo) can't be loaded as executables within the CC-spawned subprocess. The shell itself runs fine, but child processes of that shell can't execute MSYS2 binaries. This likely points to an environment issue (missing MSYSTEM, wrong PATH, or a different subprocess creation method that doesn't properly inherit the MSYS2 runtime context).

2. The stdout pipe itself is broken

Even builtin echo (which doesn't spawn an external process) fails with exit 1. This means writing to file descriptor 1 (stdout) fails in the CC subprocess. The pipe that CC sets up to capture command output isn't compatible with MSYS2's POSIX emulation layer. Writing to files bypasses this completely, which is why the redirect workaround succeeds.

Likely Root Cause

CC v2.1.45 likely changed how it creates the stdout pipe or spawns the child process on Windows. Candidates:

  • Pipe type mismatch: MSYS2 translates POSIX fd operations to Win32 handles. If CC switched to Win32 named pipes (or changed the pipe configuration in child_process.spawn), MSYS2's translation layer may not handle them correctly.
  • stdio config change: A change from 'inherit' to ['pipe', 'pipe', 'pipe'] (or similar) in the Node.js spawn() options could break MSYS2 compatibility while working fine on native Windows shells.
  • Environment propagation: If MSYSTEM=MINGW64 or related MSYS2 env vars aren't passed to the subprocess, the MSYS2 runtime can't properly initialize, which would explain why binaries in /usr/bin/ can't execute.

Workaround

Until patched, redirecting all output to files works:

echo "test" > /tmp/output.txt 2>&1; true

Then use the Read tool to read the file contents.

arbgjr · 6 months ago

Additional diagnostic: NT device path confirmed as not writable by MSYS2

Environment: Windows 11 Pro 10.0.26200, GNU bash 5.2.37(1)-release (x86_64-pc-msys), Claude Code v2.1.45

I performed independent diagnostics that confirm and extend the root cause analysis above. Key findings:

1. The stdout fd points to a Claude Code task output file via NT device path

By saving fd 1 to fd 5 before redirecting, I was able to inspect the original stdout:

exec 5>&1 1>"$HOME/fd_clean.txt"
readlink -f /proc/self/fd/5 >>"$HOME/fd_clean.txt" 2>&1
test -w /proc/self/fd/5 && echo "writable=yes" || echo "writable=no"

Result:

/proc/self/fd/5 -> C:/Device/HarddiskVolume3/Users/<user>/AppData/Local/Temp/claude/C--Users-<user>-source-repos-.../tasks/<taskid>.output
writable=no

2. MSYS2 reports the fd as NOT writable

test -w /proc/self/fd/1 returns false. This is why echo (which checks write success) returns exit code 1 — it's the bash builtin's documented behavior: "echo returns 0 unless a write error occurs."

3. The NT device path format is the smoking gun

The fd resolves to C:/Device/HarddiskVolume3/Users/... — this is a Windows NT device path, not a standard Win32 path. MSYS2's POSIX emulation layer cannot handle NT device paths as writable file descriptors. The v2.1.44 pipe-based approach used standard POSIX pipes which MSYS2 translates correctly.

4. Complete behavior matrix

| Command | Stdout fd used? | Exit code |
|---------|----------------|-----------|
| true | No | 0 |
| echo hello | Yes (builtin write to fd 1) | 1 |
| echo hello >&2 | Yes (fd 2, same issue) | 1 |
| echo hello > file | No (new fd to file) | 0 |
| ls > /dev/null 2>&1 | No (redirected) | 0 |

Workaround

Until patched, redirect to file + Read tool:

command > "$HOME/output.txt" 2>&1; true

---

This confirms @chablitzel's analysis: the spawn() change from pipe-based to file-descriptor-based stdout capture creates an fd that MSYS2 cannot write to, because it inherits a Windows file handle (NT device path) that doesn't translate to a valid POSIX writable fd.

KatayR · 6 months ago

It got fixed with the latest update but noooow stop hooks are broken...

● Ran 3 stop hooks ⎿ Stop hook error: Failed with non-blocking status code: c:users34lnst-devtmp_token.json does not exist or is disconnected

looks like it because path to hooks is messed up

jchesshircr · 3 months ago