anthropics / anthropics/claude-code
Windows/Git Bash: the Bash tool dies for the rest of the session (unexpected EOF at a line past the command / ENAMETOOLONG uv_spawn)
- Dominant language
- Python
- Stars
- 145k
- Forks
- 23.1k
- PR merge metrics
- PR metrics pending
Description
## Summary
On this Windows 11 / Git Bash workstation, the Bash tool sporadically dies for the **rest of the
session** — not just the failing command. Every subsequent Bash call fails the same way, including
a trivial one-word command, including one issued from inside a subagent. The only recovery we have
found is starting a new session. We believe the harness wraps every Bash-tool invocation in a
generated preamble (shell-snapshot sourcing, environment setup, etc.) before handing it to the
actual shell, and that on an affected session this preamble is itself malformed or oversized — the
failure is in the wrapper, not in anything the model sent.
We first noticed this on **2026-09-09**: a session's Bash tool began failing on ordinary,
previously-working commands partway through a long task, and never recovered for the rest of that
session. At the time we did not have instrumentation and assumed it was a one-off. Between
2026-09-09 and today (**2026-09-16**) we built detection, routing, and evidence-collection around
it in our own dotfiles repo (tracked as `ton77v/dotfiles#257` on our side — not an upstream
reference, just how we've been tracking it internally) so that the next occurrence would leave
usable evidence instead of another shrug. This report is written from that instrumentation and from
re-reading the failures we had already captured, not from a single fresh repro captured today.
## Two observed signatures
Both come back from the Bash tool's own error channel (never something merely echoed by a later
command's stdout — we learned to exclude that case the hard way, see "False positives we ruled
out" below). We give the exact text our own guard matches on, not a paraphrase:
Signature A — an `unexpected EOF` reported far past the end of the command actually sent:
```
/usr/bin/bash: -c: line 102: unexpected EOF while looking for matching `'
```
For a **one-line** command, `bash` reports the unterminated quote at line 102 — a line number that
does not exist anywhere in the command the model wrote. That gap is the tell: a genuine unbalanced
quote in a short command is reported at or near that command's own last line, not ~100 lines past
it. Line 102 only makes sense if it is counting lines in something much longer than the command
itself — consistent with a generated wrapper/preamble that is itself unbalanced.
Signature B — `ENAMETOOLONG` together with `uv_spawn` (libuv's process-spawn primitive; unrelated to
the `uv` Python package manager, which is coincidentally also in heavy use in this environment):
```
ENAMETOOLONG: name too long, uv_spawn
```
This one fails a layer earlier — the child process is never spawned at all, which reads as the
constructed argv/environment for the shell invocation exceeding a platform limit before `bash` ever
gets to parse anything.
We treat these as the same root cause approached from two sides: one is a malformed wrapper (an
unbalanced quote inside it), the other is an oversized one (past a spawn-time length limit).
## Environment
- OS: Windows 11 Home Single Language (build 26200)
- Shell: Git Bash (the harness's Bash tool shells out to `bash` from a Git-for-Windows install)
- Claude Code CLI: `claude --version` → `2.1.273 (Claude Code)` at the time of writing (our evidence
collector records this field on every future occurrence; the original 2026-09-09 occurrence predates it).
- Reproduces from a top-level session and from inside a subagent shelled out via the Task tool
alike; not scoped to any one command's content.
## Reproduction
Not reliably reproducible on demand — this is what has made it hard to pin down. What we can say
from the sessions where it did occur:
1. Bash tool calls succeed normally for some number of turns.
2. At some point, a Bash call — including ones with no unusual quoting, sometimes as plain as a
single `ls` or `pwd` — fails with signature A or signature B.
3. Every Bash call for the remainder of that session fails the same way. The command's own content
stops mattering; even a command with no quotes at all reproduces signature A's `unexpected EOF`.
4. Other tools (file read/write/edit, grep, glob) continue working normally. The PowerShell tool,
when available, also continues working normally — only the Bash tool is affected.
5. Starting a new session clears it; nothing we have tried clears it within the same session.
## False positives we ruled out
Two things we initially mistook for a recurrence, on **2026-09-15**, before tightening detection:
- A command's own **stdout** can innocently *quote* one of these signature strings back (e.g. `gh
issue view` printing an issue body that discusses this very bug, or a test fixture `grep` echoing
the sample text) — that is not the outage recurring, it is the outage being *discussed*. Our
detector now scans only the tool response's error-carrying fields (`stderr`/`error`/`message`),
never `stdout`/`output`.
- A **genuine** unbalanced quote the model itself wrote reports its line number inside (or right at
the edge of) the command's own line count, not far past it. We treat "far past" as more than 10
lines beyond the command's own length before calling it the harness bug rather than a model
mistake — deliberately generous, so an off-by-a-few from heredocs/continuation lines is never
mistaken for this.
## What we ruled out as the cause
- **Not command content**: reproduces on trivial, unquoted, previously-successful commands once a
session is in the affected state — the specific command sent stops being the variable.
- **Not `uv` (the Python tool)**: `uv_spawn` in signature B is libuv's internal spawn primitive,
unrelated to the `uv` Python package/dependency manager despite the name collision; we do not
believe this points at anything in our own `uv`-based tooling.
- **Not this repo's own hooks**: the failure reproduces with hooks disabled entirely; it is not a
side effect of a `PreToolUse`/`PostToolUse` hook misbehaving.
## Hypothesis
The harness generates a preamble around every Bash-tool invocation (sourcing a shell snapshot,
setting up environment/state) rather than sending the model's command to `bash` directly. On an
affected session, that generated preamble is itself malformed (an unbalanced quote inside it,
signature A) or has grown past a platform argv/env size limit (signature B) — and because the
preamble is regenerated fresh per call but apparently carries forward whatever made it malformed or
oversized in the first place (a snapshot file, accumulated session state, or similar), the failure
repeats for every subsequent call in that session rather than only the one that first tripped it.
We have not been able to capture the wrapper's own generated text directly — we can only infer its
shape from where `bash` reports the unbalanced quote (line 102, past any command we send) and from
the `ENAMETOOLONG` spawn-time failure. If there is a way to have the harness log or expose the
wrapper text itself on failure, that would let us confirm or rule this out directly.
## What we built to survive it, not to fix it
We do not expect to fix this from our side — it is in wrapper generation we cannot see into. What we
built is a local workaround-and-evidence layer, entirely in our own repo:
- A `PostToolUse`/`PreToolUse` hook pair that detects either signature in a tool response's error
channel, latches the session, and reroutes subsequent shell work to the PowerShell tool (never
itself affected) and to the file tools, rather than letting the agent retry a dead tool believing
each failure is its own mistake.
- A `SessionStart` canary that runs one throwaway `bash -c 'echo probe-ok'` at the top of every
session and raises the same early warning if that canary itself already shows a signature —
though we want to be upfront that this canary runs through a plain subprocess call, not through
the harness's own per-call wrapper (which is generated fresh for every Bash-tool invocation), so
a clean canary is evidence the workstation itself is sane, not proof this session's own wrapper
will be — it can only catch a workstation already in a bad state at session start.
- A value-free evidence collector (records counts, byte lengths, and booleans — snapshot file size
and `bash -n` parse verdict, environment variable count and total byte size, `PATH` length, cwd/
branch length and whether either contains an apostrophe — never an environment variable's actual
value) that runs automatically the first time a session latches, so the next occurrence leaves
something concrete behind instead of another anecdote.
None of this fixes the underlying wrapper — it only shortens how long an agent spends confused once
it has happened, and improves what we can hand back to you the next time it does.
## What would help from your side
- Any way to inspect or log the harness-generated preamble/wrapper text itself around a Bash-tool
call, at least on failure — everything above is inferred from `bash`'s own error output, never
from seeing the wrapper directly.
- Confirmation of whether a shell snapshot file, or any other piece of per-session state, is reused
across Bash-tool calls within a session in a way that could explain why the failure — once it
starts — repeats for every subsequent call rather than only the first.
> 🦀 **sent by [Agent System v0.22.11](https://antoniov.online/agentic-systems): Claude Code | claude-opus-5**
Contributor guide
No contributing guide indexed for this repository
Research direction
The report names no upstream files, tests, or entry points. Start by reproducing the session-level failure on Windows with Git Bash and comparing the error-channel signatures against any exposed generated wrapper or per-session snapshot. Done means confirming or rejecting the wrapper/state hypothesis and documenting a reliable fix or diagnostic path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- bash
- Domain
- cli, operating-systems, tooling
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100