Skip to main content
← Back to list
01Issue
BugShippedSwamp CLIPublic
Assigneeshammz

Relationships

#2833 Concurrent embedded deno extraction races: stale temp-file cleanup deletes another process's in-flight .deno.tmp file (chmod ENOENT)

Opened by hammz · 9/30/2026· Shipped 9/30/2026

Summary

When two swamp processes extract the embedded deno binary at the same time, one can delete the other's in-flight temp file, so the victim fails with No such file or directory (os error 2): chmod '~/.swamp/deno/.deno.tmp.<uuid>'. Whatever command triggered the extraction (e.g. swamp extension pull) then fails.

Cause

EmbeddedDenoRuntime.extractEmbeddedDeno() (src/infrastructure/runtime/embedded_deno_runtime.ts) does:

  1. cleanupStaleTempFiles(swampDir) — removes every .deno.tmp.* entry in ~/.swamp/deno
  2. Deno.writeFile(tmpPath, …) to its own .deno.tmp.<uuid>
  3. Deno.chmod(tmpPath, 0o755) → Deno.rename(tmpPath, targetBinary)

Step 1 assumes every temp file is left over from a crashed extraction, but it cannot tell those apart from a temp file a concurrent live process is writing. Interleaving:

  • Process A completes step 2
  • Process B runs step 1 and deletes A's temp file
  • A's chmod fails with ENOENT

The in-process extractionPromise dedupes only within one process, not across processes. The cleanup was introduced in #2382 (swamp-club#2038, atomic-rename ETXTBSY fix).

Extraction only happens when ~/.swamp/deno/.version doesn't match the binary, so this is a cold-start race: first commands after installing/upgrading swamp, when more than one runs concurrently (parallel scripts, background jobs, multiple terminals, CI).

Observed

swamp-uat run https://github.com/swamp-club/swamp-uat/actions/runs/36761442017/job/110044726736 (binary 20260930.184839.0-sha.e47a5c51), tests/cli/extension/journeys/full_lifecycle_test.ts, run under deno test --parallel with a shared HOME:

Error: Install partially applied for @stack72/system-extensions — files extracted but bundling/importing the extension failed (No such file or directory (os error 2): chmod '/home/[REDACTED]/.swamp/deno/.deno.tmp.7a1fc3f8-79ab-4203-b8a6-331f16f0d814'). Run `swamp doctor extensions` to inspect, or retry `swamp extension pull @stack72/system-extensions` to reconcile.

The next UAT run passed (the extraction had landed by then), so it presents as a flake.

Steps to reproduce

  1. Install a fresh compiled swamp binary (or delete ~/.swamp/deno/.version)
  2. Start several commands that need deno at once, e.g. swamp extension pull <ext> in several repos in parallel
  3. Occasionally one fails with the chmod … .deno.tmp.* … os error 2 error above

Suggested fix

Only remove temp files that are clearly abandoned, e.g. mtime older than ~10 minutes, so crash leftovers still get cleaned without racing live extractions. The rest of the flow is already concurrency-safe (per-process UUID temp paths + atomic rename). Unit test: a fresh .deno.tmp.* survives cleanup, one aged with Deno.utime is removed.

This is a CLI bug, not a UAT bug — isolating SWAMP_HOME per UAT test would only mask it.

Environment

  • swamp 20260930.184839.0-sha.e47a5c51 (compiled/standalone)
  • Linux (GitHub Actions ubuntu runner)
02Bog Flow
✓OPEN✓TRIAGED✓IN PROGRESS✓SHIPPED+ 1 MOREASSIGNED+ 5 MOREREVIEW+ 7 MOREPR_MERGED+ 2 MORESESSION_SUMMARIZED

Shipped

9/30/2026, 8:31:38 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
hammz assigned hammz9/30/2026, 7:25:27 PM

Sign in to post a ripple.