Hook stdout incorrectly routed to stderr when using Git Bash on Windows
Description
When running Claude Code from Git Bash on Windows, hook commands that write to stdout have their output incorrectly appear on stderr. This causes Claude Code to display "hook error" messages even though hooks complete successfully with exit code 0.
Environment
- OS: Windows 11
- Shell: Git Bash (MINGW64)
- Node.js: v22.14.0
- Claude Code: Latest
Root Cause
Git Bash's pipe implementation on Windows has a compatibility issue with Node.js's stream handling. When stdin is provided via pipe (echo | node), stdout writes get routed to stderr.
Reproduction
# In Git Bash on Windows:
# stdout goes to stderr (BUG)
echo '{}' | node -e "console.log('test')" 1>/tmp/stdout.log 2>/tmp/stderr.log
cat /tmp/stdout.log # Empty
cat /tmp/stderr.log # Contains "test"
# These work correctly:
node -e "console.log('test')" < /tmp/input.json # File redirect - OK
node -e "console.log('test')" <<< '{}' # Here-string - OK
Impact
All hooks that write JSON responses to stdout appear to fail from Claude Code's perspective, even though they execute correctly.
Suggested Fixes
- Check stderr for valid JSON when exit code is 0: If a hook exits successfully but has JSON on stderr and nothing on stdout, treat the stderr content as the response.
- Use file-based IPC on Windows: Instead of piping, write input to a temp file and read output from a temp file.
- Use here-string or file redirect: Instead of
echo | node hook.mjs, usenode hook.mjs <<< "$input"or file redirection.
Test Matrix
| Input Method | Shell | stdout Destination |
|--------------|-------|-------------------|
| echo \| node | Git Bash | stderr (BUG) |
| node < file | Git Bash | stdout (OK) |
| node <<< str | Git Bash | stdout (OK) |
| echo \| node | PowerShell | stdout (OK) |
| echo \| node | cmd.exe | stdout (OK) |
Additional Context
This appears to be a known compatibility issue between Git Bash (MINGW64) and Node.js on Windows. The file descriptors are correctly numbered inside Node.js, but the shell's pipe routing is incorrect.
4 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Thanks for flagging the related issues.
After investigating, this does appear to be related to the same underlying Git Bash stdout capture bug on Windows. My specific case involves hook invocation (piping JSON to Node.js hooks), but the root cause is the same: stdout from subprocesses isn't captured correctly in Git Bash/MINGW64.
Key finding from my investigation:
echo | node script.js), stdout writes appear on stderr.cmd/.exesuffixes, BASH_ENV) don't help for piped stdin scenariosClosing as duplicate - will add my findings to #18469 for visibility.
For anyone hitting hook-specific errors: Claude Code shows "hook error" messages because hook stdout is routed to stderr, which Claude Code interprets as an error.
Closing as duplicate of #18469. Added our hook-specific findings there.
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.