anthropics / anthropics/claude-code

[BUG] Windows: Bash tool commands are silently truncated at ~8,181 chars of the bash.exe -c argument, and every \\ is halved

Abierto
#92,543 0 comentarios 0 reacciones 0 asignados Ver en GitHub
area:bash bug has repro platform:windows
Lenguaje dominante
Python
Estrellas
145k
Forks
23.1k
Métricas de merge de PR
Métricas de PR pendientes

Descripción

### What happens

On Windows the Bash tool passes the whole command to Git's `bash.exe` as a single `-c` argument:

```
bash.exe -c "source && export TEMP=... && eval '' && pwd -P >| "
```

(That's `/proc/$$/cmdline` from inside the tool's shell.) Two things go wrong at the node → bash.exe argv hand-off, and I can reproduce both with plain Node spawning `bash.exe` directly, so this isn't the wrapper — it's the transport:

1. **The `-c` argument is cut off between 8,181 and 8,190 characters.** Bash then reports `unexpected EOF while looking for matching `'`` (or `here-document ... delimited by end-of-file`) and nothing runs. Because the wrapper rewrites every `'` as `'"'"'`, the line number in the error is just the last `'` in the user's text before the cut, which sends you hunting for a quoting bug that doesn't exist. libuv only refuses at 32,767 (`ENAMETOOLONG`), so anything between ~7.5K and 32K chars fails this way with no diagnostic pointing at length.
2. **Every doubled backslash arrives halved.** `A\\B` reaches bash as `A\B`, `G\\\\H` as `G\\H` — inside a quoted heredoc too. libuv quotes the argument by MS-CRT rules (a backslash is only doubled before a `"`), while the MSYS2 runtime parses `\\` inside a double-quoted argument as an escape. Writing the same script to a file and running the file is byte-exact.

A census of my own transcripts (7,815 Bash commands, 37 sessions) shows 0 truncation failures under 8K expanded chars and 25 of 29 at 9K and above; plus a handful of `SyntaxError: unterminated string literal` in Python heredocs that were the halving.

### Repro (no Claude Code needed)

```js
// node repro.js -- Node 24.19, Git for Windows 2.55.0.windows.3
const { spawnSync } = require('node:child_process');
const bash = 'C:\\Program Files\\Git\\usr\\bin\\bash.exe'; // same result with bin\bash.exe
for (const n of [8100, 8180, 8190, 8200, 9000]) {
const script = 'echo START; : ' + 'a'.repeat(n - 24) + '; echo END';
const r = spawnSync(bash, ['-c', script], { encoding: 'utf8' });
console.log(script.length, JSON.stringify(r.stdout.trim()), r.stderr.trim().slice(0, 60));
}
// 8100 "START\nEND"
// 8180 "START\nEND"
// 8190 "START" <- tail gone, no error
// 8200 "START"
// 9000 "START"
const r = spawnSync(bash, ['-c', "printf '%s\\n' 'A\\\\B G\\\\\\\\H' | /usr/bin/od -c"], { encoding: 'utf8' });
console.log(r.stdout); // A \ B G \ \ H <- sent A\\B G\\\\H
```

Through the Bash tool the ceiling for the user's command is lower — roughly 7,000 chars / 100 lines — because the wrapper text and the `'"'"'` expansion share the same 8K budget.

### Expected

Either the command runs, or the tool says it's too long. Today it does neither: the command is silently truncated and bash reports a quoting error inside the body.

### Suggested fix

On Windows, hand the script to bash via stdin or a temp file (`bash ` / `bash -s < file`) instead of as a `-c` argument — that removes both the length cap and the backslash re-interpretation. Failing that, refuse commands whose assembled `-c` argument exceeds ~8,100 chars with a clear message.

### Environment

- Claude Code 2.1.263, Windows 11 Enterprise 10.0.26200
- Node v24.19.0 (nvm4w), Git for Windows 2.55.0.windows.3 (`bin\bash.exe` wrapper → `usr\bin\bash.exe`, MSYS2 bash 5.3.15)
- Same behaviour with `CLAUDE_CODE_GIT_BASH_PATH` unset (default discovery)

Guía de contribución

No hay ninguna guía de contribución indexada para este repositorio

Línea de trabajo

Start with the plain Node spawnSync repro against Git's bash.exe and compare the 8,180/8,190-character cases plus the backslash sample. Then trace the Bash tool's Windows command transport that builds the bash.exe -c argument. Done means commands are passed without truncation or backslash changes, or overly long commands receive a clear error.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
bash, git, javascript, node.js
Área
cli, operating-systems, tooling
Tipo de issue
Error
Dificultad
4/5
Tiempo estimado
3-5 días
Estado de actividad
Activo
Claridad
Bastante claro
Aptitud para principiantes
52/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.