Bash tool silently returns empty output when /tmp/claude-$UID/ exceeds an auto-applied tmpfs quota (systemd ≥256 + kernel ≥6.6)
Preflight
- This is a follow-up to #51814 (closed as inactive — "Please open a new issue if this is still relevant") and is related to #42461. Both describe the same silent-empty-output failure; I'm opening a fresh report per the maintainer's request, with new evidence that this now occurs on stock, unconfigured systems.
Summary
Every Bash tool call — ls, echo, !cmd, even true — silently returns empty output (with a confusing non-zero exit code) while the same commands work fine in a normal terminal. The root cause is that the Bash tool captures stdout/stderr through a file under /tmp/claude-$UID/, and when the per-user tmpfs quota on /tmp is exhausted, that write fails with EDQUOT. The error is never surfaced to the user or the model, so the tool just returns empty output. rm -rf /tmp/claude-$UID/ instantly restores functionality.
This was extensively documented in #51814; I'm adding two pieces of new signal that I believe justify a fix rather than another auto-close.
What's new since #51814
1. The per-user tmpfs quota is no longer opt-in — modern distros apply it automatically.
The reporter in #51814 had a manually-tuned 9.5G quota. I never configured any quota. Mine comes entirely from upstream defaults:
- systemd ≥256 ships
/usr/lib/systemd/system/tmp.mountwithOptions=...,x-systemd.graceful-option=usrquota, andsystemd-user-runtime-dirauto-applies a per-UID quota (~80% of the tmpfs) on/tmpand/dev/shmat login. - Linux ≥6.6 added tmpfs quota support (
CONFIG_TMPFS_QUOTA), so that graceful option actually takes effect.
Result on my machine, with nothing in my fstab or any manual quota setup:
$ grep ' /tmp ' /proc/mounts
tmpfs /tmp tmpfs rw,nosuid,nodev,nr_inodes=1048576,inode64,huge=within_size,usrquota 0 0
As systemd ≥256 and kernel ≥6.6 become the norm, this silent failure becomes a default-configuration bug, not an edge case for users with custom quotas.
2. The filler wasn't Claude Code's own output — so rotating /tmp/claude-$UID/ alone wouldn't fully fix it.
In my case the quota was exhausted by ~6 GB of leaked pytest temp dirs (/tmp/.../pytest-of-*/) created by test runs Claude itself launched, not by accumulated CC tool outputs. The deeper fragility is that the Bash tool captures stdout/stderr through a file on a /tmp that shares one per-user quota with everything the agent does (test runs, builds, scratch files). When anything saturates that quota, output capture silently EDQUOTs and the tool returns empty output.
Why it's so hard to diagnose
- Presents identically to dozens of unrelated failures (empty output + opaque non-zero exit code).
df /shows plenty of free space — the limit is a quota on the tmpfs, not disk space on/.- The interactive terminal keeps working because it writes to a pty, not a
/tmpcapture file — so users conclude their shell is healthy and the problem is "Claude Code itself."
Steps to reproduce
- On a system where
/tmpis tmpfs with a per-userusrquota(default on systemd ≥256 + kernel ≥6.6). - Fill the per-user quota under
/tmp— e.g. let Claude run a test suite that leaks temp dirs, orfallocate/dda large file as the same user. - Run any Bash tool call (even
echo hi). It returns empty output with a non-zero exit code;!cmddoes too. rm -rf /tmp/claude-$UID/(or free the quota) → commands work again immediately, no restart needed.
Environment
- Claude Code: 2.1.162
- OS: Arch Linux
- Kernel: 7.0.11
- systemd: 260
/tmp: tmpfs withusrquota(per-UID cap auto-applied by systemd, ~6.1G)- Shell: zsh
- Platform: Anthropic API
Suggested fixes (in addition to the original list in #51814)
- Surface the write error. If the output-capture write fails with
EDQUOT/ENOSPC, report it in the tool result instead of returning empty output + an opaque exit code. This single change would have turned a multi-hour investigation into a one-line diagnosis. - Don't share the quota'd
/tmpfor output capture. AllowTMPDIR/a configurable capture dir, or place capture files somewhere not subject to the per-user tmpfs quota, so unrelated agent activity (test runs, builds) can't starve Claude Code's own I/O. - Preflight / health check. At startup and on
EDQUOT, check remaining tmpfs quota for/tmp/claude-$UID/and warn loudly.
Workarounds (for others landing here)
- Immediate unblock:
rm -rf /tmp/claude-$UID/(or just the offending subdir). - Stop pytest recurrence at the source — drop temp dirs after passing runs so they can't accumulate:
export PYTEST_ADDOPTS="-o tmp_path_retention_policy=failed"(keeps failed runs for debugging). - Bulletproof escape hatch for large temp data: point at disk-backed storage outside the quota'd tmpfs, e.g.
export TMPDIR=$HOME/.cache/tmp(and for pytest,--basetemp).
Even just fix #1 (surfacing the error) would eliminate the worst part of this: the silent, undiagnosable failure.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗