[BUG] Windows: Bash tool's composed bash -c string is silently cut at 8186 chars by MSYS (7774 left for the command); backslash runs halved
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet (closest: #88311, #68337, #71591, #26742, all auto-closed for inactivity)
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code
What's Wrong?
On Windows the Bash tool composes one bash -c "<wrapper>" string: snapshot source, TEMP/TMP export, extglob/unsetenv guards, eval '<command>', < /dev/null, and a pwd -P >| <Temp>/claude-XXXX-cwd epilogue. Git for Windows' MSYS bash keeps only the first 8186 characters of that -c argument and silently drops the rest.
Measured on this machine (reproduced twice, in two sessions):
- Cap: exactly 8186 decoded characters (counted in code points:
é,€and emoji each count 1). 8186 passes, 8187 is cut. Same number throughbin\bash.exeandusr\bin\bash.exe, and when Python spawns bash.exe directly with the identical wrapper string, so this is in Git Bash/MSYS, not in Node's spawn. - Wrapper overhead: exactly 412 characters here (prefix 337, suffix 75); it depends on username and Temp path. That leaves 7774 characters for the model's command.
- Per-character cost after the tool's escaping: ordinary characters,
",$, newline and non-ASCII = 1;'= 5 (sent as'"'"'). English prose heavy with apostrophes hits the cap well under 2 KB (1561 apostrophes alone fill it). - Separately, MSYS halves backslash runs in the
-cargument even inside single quotes: a run of n backslashes arrives as ceil(n/2) (\\→\,\\\\→\\), except directly before". Verified through the tool:printf '%s|' 'a\b' 'a\\b' 'a\\\b' 'a\\\\b'printsa\b|a\b|a\\b|a\\b|. This silently corrupts regexes and Windows paths inside heredocs.
What the truncation does depends on how far over the cap the string is:
| Over by | Effect |
|---|---|
| 1–62 | The command runs, but the epilogue is cut: cwd tracking is lost and a stray partial-name file can be written in Temp, or bash reports Is a directory. No error is surfaced for the command itself. |
| 63–75 | The < /dev/null redirect is cut; nothing runs. |
| > 75 | The eval closing quote is cut; nothing runs; bash reports the misleading unexpected EOF while looking for matching ''`. |
In practice the model hits this with any heredoc or inline script over ~7 KB, or much smaller text with many apostrophes. Over three weeks I logged 13 such failures in one project. Each costs a failed round trip, and the >75 case has sometimes already run a SendMessage or other side effect earlier in the same turn before the Bash call failed. #88311 reports the degenerate end state of the same mechanism, where a large inlined snapshot alone exceeds the cap and every call fails.
What Should Happen?
The Bash tool should not pass the composed script on the command line on Windows. The PowerShell tool already avoids this: it passes the script in the CLAUDE_CODE_SHELL_LAUNCHER_SCRIPT environment variable and runs Invoke-Expression on it. Doing the equivalent for bash (env var, temp file run with bash <file>, or stdin) removes the cap and the backslash halving in one change, and makes #88311 impossible. Failing that, the tool should at least refuse commands whose escaped size exceeds the cap with a clear error instead of truncating silently.
Error Messages/Logs
# Command 34 characters over the budget: bash receives exactly 8186 chars and the epilogue is cut
$ sed -z -n 3p /proc/$$/cmdline | wc -m; sed -z -n 3p /proc/$$/cmdline | tail -c 40
8187
< /dev/null && pwd -P >| /c/Users/alan/
/usr/bin/bash: line 97: /c/Users/alan/: Is a directory
# Command well over the budget
/usr/bin/bash: -c: line 1: unexpected EOF while looking for matching `''
# Backslash halving inside single quotes
$ printf '%s|' 'a\b' 'a\\b' 'a\\\b' 'a\\\\b' 'q\\"q' 'end\\'; echo
a\b|a\b|a\\b|a\\b|q\\"q|end\|
Steps to Reproduce
- Windows, Git for Windows bash as the Bash tool shell.
- Run
cp /proc/$$/cmdline /tmp/cl.binthrough the Bash tool to capture the exact wrapper; split on NUL, take argv[2]; the prefix ends ateval 'and the suffix starts at' < /dev/null. Overhead = prefix + suffix (412 here). - Build a command
echo PASS #+ N ×a, wrap it exactly as the tool does ('→'"'"', prefix + suffix +; echo TAIL), and spawn"C:\Program Files\Git\bin\bash.exe" -c <string>from Python withsubprocess.run. Binary-search N: TAIL stops appearing when the total reaches 8187. - Confirm live: send the Bash tool a generated, numbered command sized (8186 − overhead + 34) characters whose first line is
sed -z -n 3p /proc/$$/cmdline | wc -m; sed -z -n 3p /proc/$$/cmdline | tail -c 40. It prints 8187 (8186 + NUL) and a tail cut mid-path, as above. Hand-typed uniform filler is unreliable for this; use numbered tokens. - Backslashes: run the
printfline above through the Bash tool.
Claude Model
Fable 5.1
Is this a regression?
No, this is a long-standing limitation (reports back to #26742 in Feb 2026)
Claude Code Version
2.1.295 (Claude desktop app, Code tab, Windows)
Platform
Anthropic API (Claude desktop app, Code tab)
Operating System
Windows 11 Pro 10.0.26200
Terminal/Shell
Other: Git Bash (git 2.51.2.windows.1, GNU bash 5.2.37(1)-release x86_64-pc-msys)
Additional Information
Related, all auto-closed for inactivity: #88311 (same mechanism, snapshot-sized), #68337, #71591, #26742 (apostrophe in username → same '"'"' escaping cost). Workaround in use: a PreToolUse hook that blocks Bash commands whose escaped size (length + 4 × apostrophes) exceeds 7700 and tells the model to use the Write tool plus bash <file> instead.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗