Bash tool falsely reports 'temp filesystem … is full (0MB free)' on any empty-stdout + non-zero-exit command
Summary
The Bash tool falsely reports the temp filesystem at <path> is full (0MB free). The child process's stdout/stderr writes failed with ENOSPC. on any command whose stdout is empty AND whose exit code is non-zero, even though no ENOSPC ever occurred and the underlying filesystem has terabytes free.
Environment
- Claude Code: 2.1.160 (also seen on 2.1.150 / 2.1.158 / 2.1.159)
- Platform: macOS 14, Darwin 23.6.0, x86_64
- Install location:
~/.local/share/claude/versions/2.1.160 - Tasks dir filesystem: APFS data volume, 14 TB free
Reproduction
$ false
That's all that's needed. Empty stdout + exit 1 reliably produces:
Command output was lost: the temp filesystem at
/private/tmp/claude-501/-Users-dlr-src-mdfind/<session>/tasks is full (0MB free).
The child process's stdout/stderr writes failed with ENOSPC.
Free up space or set CLAUDE_CODE_TMPDIR to a directory on a filesystem with room.
Other reliable triggers:
grep notpresent file_that_exists(exit 1, empty stdout)test -e /nonexistent(exit 1, empty stdout)- Any
cmd 2>/dev/nullthat exits non-zero with no captured stdout
Expected
code=1, stdout="", no filesystem warning unless a write actually returned ENOSPC.
Actual
The "0MB free" message is substituted into stdout and presented to the model as if the filesystem really were full.
Disk state at the moment of the false positive
$ df -k /private/tmp/claude-501/-Users-dlr-src-mdfind/<session>/tasks
/dev/disk2s1 19531432968 4959348724 14541659824 26% 6078678 145416598240 0% /System/Volumes/Data
Independent verification with system Node v25.6.1 — fs.statfsSync on the exact path the harness checks, called 10× in a row:
bavail: 3635414955 bsize: 4096 → 14,200,839 MB free
Every iteration returned the same value.
Root cause
The diagnostic function in the binary (de-mangled from minified):
async function pSf(outputPath) {
try {
const dir = path.dirname(outputPath);
const s = await fs.promises.statfs(dir);
const freeM = Math.floor(s.bavail * s.bsize / 1048576);
if (freeM < 10)
return `Command output was lost: the temp filesystem at ${dir} is full (${freeM}MB free). …`;
if (s.files > 0 && s.ffree < 1000)
return `… out of inodes (${s.ffree} free). …`;
} catch {}
return null;
}
Call site:
} else if (this.taskOutput.stdoutToFile
&& capturedStdout === ""
&& exitCode !== 0
&& exitCode !== 137 /* SIGKILL */) {
const msg = await pSf(this.taskOutput.path);
if (msg) result.stdout = msg;
}
Two issues:
- No
ENOSPCerrno is ever observed.pSfis invoked purely on the heuristic "empty stdout + non-zero exit" — it then guesses the cause was disk pressure and presents the guess as fact. Any normal non-zero-exit command with empty stdout triggers it.
- The
statfsreading isn't sanity-checked. The bundled Node inside the SEA appears to be v24.3.0 (visible instringson the binary). For some reason itsstatfsis readingbavail * bsizeas < 10 MB on a path the system-installed Node v25.6.1 reads as ~14 TB. Whether that's a libuv/SEA quirk on macOS or something else,pSfpropagates the bogus reading to the user with high confidence — including a "setCLAUDE_CODE_TMPDIR" suggestion that probably won't help.
Suggested fix
Either:
(a) Only emit the diagnostic when the harness has actually observed an ENOSPC errno from the write to the output file. Tie this to a real write-error event, not "empty + non-zero".
(b) If keeping the heuristic, sanity-check the statfs result: skip the message if s.blocks === 0, if s.bavail > s.blocks, or if the value would imply the filesystem is impossibly small. Optionally cross-check by attempting a 1-byte write into the directory and only emit the alarm if that write actually returns ENOSPC.
Regression window
~/.local/share/claude/versions/ on the affected machine:
2.1.150 May 24
2.1.158 May 31
2.1.159 May 31
2.1.160 Jun 1
Symptom has been frequent for two weeks. The 2.1.150 install date matches that exactly — earlier versions did not exhibit this. Likely introduced in 2.1.150.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗