Describe the bug
When the volume holding os.tmpdir() runs out of space after the per-project tmp directory was created, writing the module tmp copy fails. The failure is only logged via debugFs, but the module is still marked as cached (transformResult.__vitestTmp = tmpFile). Subsequent fetches of the same module then return a result pointing to that file, which was never written, and the worker fails with:
Error: ENOENT: no such file or directory, open '<TMPDIR>/<id>/ssr/<sha1>'
The real cause (ENOSPC) is invisible in the output, so the failure looks like a random missing-file flake.
Where (vitest 5.0.3, dist/chunks/index.DpLw24bj.js)
cacheResult() (~line 6495): .catch(...) only calls debugFs$1?.("failed to cache ...") and returns result.
- Caller in the
cachePath == null / makeTmpCopies branch (~lines 6312-6322): .then(() => { if (transformResult) transformResult.__vitestTmp = tmpFile; ... }) runs also after a failed write.
- Next fetch (~line 6313):
if (typeof tmpPath === "string") return getCachedResult(result, tmpPath) returns the path of the missing file.
5.0.3 already serves the first result inline after a failed write, but the __vitestTmp marker is still set, so the second fetch of that module breaks. Same behaviour in 5.0.1.
Reproduction
Minimal project: src/a.ts (export const a = () => 1), src/b.ts (imports a), three test files importing b. Run on macOS with a 3 MB HFS+ disk image mounted as TMPDIR, filled so only a few KB remain:
hdiutil create -size 3m -fs HFS+ -volname SMALLTMP small.dmg
hdiutil attach small.dmg -nobrowse
mkfile -n <free-8>k /Volumes/SMALLTMP/fill # leave ~8 KB free
TMPDIR=/Volumes/SMALLTMP npx vitest run
Result with 8 KB left: Test Files 2 failed | 1 passed (3) on 5.0.1, 1 failed | 2 passed (3) on 5.0.3, with ENOENT ... /ssr/<sha1>. With 12 KB or more left the run passes; with 0 KB left mkdir fails with a clear ENOSPC.
Expected
- Do not set
__vitestTmp when the write failed (or verify the file exists before returning getCachedResult), and keep serving the module inline.
- Surface the underlying ENOSPC/EIO error instead of only a debug log.
Environment
vitest 5.0.1 / 5.0.3, Node v25.4.0, macOS arm64 (observed originally on a Linux CI runner with a nearly full root volume).
Describe the bug
When the volume holding
os.tmpdir()runs out of space after the per-project tmp directory was created, writing the module tmp copy fails. The failure is only logged viadebugFs, but the module is still marked as cached (transformResult.__vitestTmp = tmpFile). Subsequent fetches of the same module then return a result pointing to that file, which was never written, and the worker fails with:The real cause (ENOSPC) is invisible in the output, so the failure looks like a random missing-file flake.
Where (vitest 5.0.3, dist/chunks/index.DpLw24bj.js)
cacheResult()(~line 6495):.catch(...)only callsdebugFs$1?.("failed to cache ...")and returnsresult.cachePath == null/makeTmpCopiesbranch (~lines 6312-6322):.then(() => { if (transformResult) transformResult.__vitestTmp = tmpFile; ... })runs also after a failed write.if (typeof tmpPath === "string") return getCachedResult(result, tmpPath)returns the path of the missing file.5.0.3 already serves the first result inline after a failed write, but the
__vitestTmpmarker is still set, so the second fetch of that module breaks. Same behaviour in 5.0.1.Reproduction
Minimal project:
src/a.ts(export const a = () => 1),src/b.ts(importsa), three test files importingb. Run on macOS with a 3 MB HFS+ disk image mounted asTMPDIR, filled so only a few KB remain:Result with 8 KB left:
Test Files 2 failed | 1 passed (3)on 5.0.1,1 failed | 2 passed (3)on 5.0.3, withENOENT ... /ssr/<sha1>. With 12 KB or more left the run passes; with 0 KB leftmkdirfails with a clear ENOSPC.Expected
__vitestTmpwhen the write failed (or verify the file exists before returninggetCachedResult), and keep serving the module inline.Environment
vitest 5.0.1 / 5.0.3, Node v25.4.0, macOS arm64 (observed originally on a Linux CI runner with a nearly full root volume).