Hook stdout incorrectly routed to stderr when using Git Bash on Windows

Status Fixed / completed
Maintainer reply None cached
Activity 4 comments · opened Jan 22, 2026 · closed Jan 23, 2026

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

  1. 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.
  1. Use file-based IPC on Windows: Instead of piping, write input to a temp file and read output from a temp file.
  1. Use here-string or file redirect: Instead of echo | node hook.mjs, use node 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.

View original on GitHub ↗

4 Comments

github-actions[bot] · 8 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/18469
  2. https://github.com/anthropics/claude-code/issues/18748
  3. https://github.com/anthropics/claude-code/issues/19746

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

cubantobacco · 8 months ago

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:

  • When Git Bash pipes input to Node.js (echo | node script.js), stdout writes appear on stderr
  • This affects both shell scripts with shebangs AND direct Node.js execution via pipe
  • The workarounds from #18469 and #18748 (using .cmd/.exe suffixes, BASH_ENV) don't help for piped stdin scenarios

Closing 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.

cubantobacco · 8 months ago

Closing as duplicate of #18469. Added our hook-specific findings there.

github-actions[bot] · 8 months ago

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.