[BUG] Cowork sandbox: disk exhaustion is silent, and model-authored tests leak temp dirs at scale
Product: Claude Cowork (cloud sandbox session) · Date observed: 2026-08-09/10
Environment: Linux 6.18.5-fc-v20 x86_64, Python 3.11.15, 252 GB volume, 7.8 GB RAM
Summary
A long-running Cowork session filled its writable disk allowance and every subsequent
shell command began failing on write. There was no warning at any threshold, df output
actively misled diagnosis, and the underlying cause was accumulated temp directories
created by model-authored test code — 214 tempfile.mkdtemp() call sites across 55
test files, most with no cleanup — which had been running on every suite execution for
roughly a month.
There are two separable issues here and I think the second is the more important one.
Issue 1 — the failure is silent and the diagnostics mislead
Symptoms, in the order they appeared:
- Commands slowed dramatically, then began failing on write with no clear error attribution.
df -h /reported 252G total, 42G used, 0 Avail, 100%. "42G used" against a 252G
volume reads as plenty of headroom; the volume is not the limit, the session's writable
allowance is. Nothing in the output says so.
- No warning was emitted at 80%, 90%, or 99%. The first signal was failure.
What made it hard to attribute: du -x --max-depth=1 /tmp reported /tmp at ~31 GB while
its largest visible child was 80 MB. The size was spread across ~185,000 sibling
directories, which no depth-limited summary surfaces.
Expected: a warning as the session approaches its writable limit, and df output (or a
documented equivalent) that reflects the allowance actually in force rather than the
underlying volume.
Issue 2 — model-authored tests leaked at scale for a month, invisibly
This is the part I'd prioritise.
The leak is the standard shape:
def setUp(self):
self.tmp = tempfile.mkdtemp() # no addCleanup, no tearDown
In this repository that pattern appears at 214 call sites across 55 test files, nearly
all of it written by Claude over a month of agent-driven development. Every suite run left
its temp directories behind. The accumulated state at failure:
$ find /tmp -mindepth 1 -maxdepth 1 -type d | wc -l
185541
$ du -sh /tmp
~30G
Why it is worth reporting rather than just fixing:
- A single run looks completely correct. The tests pass, the workspace is clean, the
assertions are sound. The defect only exists in aggregate across runs, so no test,
review, or lint step that examines one execution can see it.
- It survived a review system explicitly built to catch this class of thing. This
project runs 26 specialist review lenses over every change, including testability and
code-quality lenses that fire on every code diff. None flagged the missing cleanup,
because each individual mkdtemp is locally fine.
- The model generated the pattern consistently. This is not one careless file. It is
the same omission reproduced across 55 files, which suggests a systematic default rather
than an accident — model-generated unittest setUp code appears to reach for
tempfile.mkdtemp() without the paired addCleanup(shutil.rmtree, ...) far more often
than not.
Suggested directions, in rough priority order:
- Bias model-generated test scaffolding toward
tempfile.TemporaryDirectory()or
addCleanup(shutil.rmtree, path, ignore_errors=True) whenever mkdtemp is emitted in a
setUp. This is a small, high-leverage default.
- Surface resource accumulation in long-running sandbox sessions — even a single line when
the writable allowance crosses a threshold would have turned a multi-hour diagnosis into
a one-minute one.
- Consider whether the sandbox should sweep
TMPDIRbetween long-running task phases.
Reproduction
- Start a Cowork cloud session on a Python repository whose tests call
tempfile.mkdtemp() in setUp without cleanup (or ask Claude to write a few dozen
unittest test cases that need a temp workspace — in my experience this reproduces the
pattern directly).
- Run the suite repeatedly over a long session.
- Observe
find /tmp -mindepth 1 -maxdepth 1 -type d | wc -lgrowing monotonically. - Continue until the writable allowance is exhausted. Observe that the first signal is
command failure, and that df reports low "used" against high "total" with 0 available.
Workaround applied
Root-level fix rather than 55 individual teardowns — the test package now pointstempfile.tempdir at one session directory and removes it at exit, so every mkdtemp in
the suite and in code under test lands inside it:
_TMP_ROOT = tempfile.mkdtemp(prefix="tp-tests-")
tempfile.tempdir = _TMP_ROOT
os.environ["TMPDIR"] = _TMP_ROOT
atexit.register(shutil.rmtree, _TMP_ROOT, ignore_errors=True)
Recovering the session required deleting ~185k directories in batches; rm still succeeded
while writes were failing, which was the only thing that made recovery possible in place.