Environment
- Determinate Nix 3.20.0 (
nix (Determinate Nix 3.20.0) 2.34.6)
- macOS, multi-user daemon install
sandbox = false, sandbox-fallback = true (the macOS defaults)
ca-derivations enabled; the affected derivations are content-addressed (__contentAddressed = true, outputHashMode = recursive)
What happened
A flake build producing many small content-addressed derivations (a per-package Go builder) was interrupted on macOS. Subsequent builds of one of those derivations then failed persistently:
> can't create /nix/store/591363gjfzandixiang98azyh4am389p-godyn-compile-github-com-gobwas-glob-match/pkg.a: open …: permission denied
Forensics on that output path:
$ ls -ld /nix/store/591363gjfzandixiang98azyh4am389p-godyn-compile-github-com-gobwas-glob-match
drwxr-xr-x 3 _nixbld3 nixbld 96 Jun 6 12:40 …
$ nix path-info /nix/store/591363gjfzandixiang98azyh4am389p-godyn-compile-github-com-gobwas-glob-match
error: path '/nix/store/591363…' is not valid
i.e. an unregistered directory stranded at the output path, owned by build user _nixbld3, mode 755. The retry's builder runs as a different _nixbld user: mkdir -p "$out" succeeds on the existing directory, every subsequent write fails EACCES, and under the sticky-bit store nothing short of root can remove it. The store also accumulated many stranded *.drv.out.lock files from the interrupted runs.
Recovery is also broken
$ nix store delete /nix/store/*-godyn-compile-*
don't know how to build these paths:
/nix/store/591363… (and ~20 other unregistered strays)
…
0 store paths deleted, 0.0 KiB freed
nix store delete has no handle on unregistered debris (it only operates on valid store paths). The only remediation that worked was manual surgery — sudo rm -rf of each invalid path inside /nix/store — after which the build progressed normally (verified).
Expected behavior
Any one of these would prevent or heal the wedge:
- Interrupt cleanup removes the in-progress output directory (and its
.out.lock).
- Output-path preparation deletes stale invalid paths at the output location before handing
$out to the builder — parity with the input-addressed "path … is invalid; removing it" behavior.
- Some supported command can remove unregistered debris from the store without manual
rm.
Mechanism hypothesis (unconfirmed — happy to be corrected)
With sandbox = false, the builder writes the real store location directly, so an interrupt strands the partial output in place; sandboxed (linux-default) builds appear immune in our usage of the same derivations, presumably because the build happens in a private location until registration. We are currently reading the 2.34.x output-path-preparation/cleanup codepath to confirm where the cleanup is skipped for the unsandboxed/CA case and to try to pinpoint a concrete fix — we'll follow up here with what we find, and we're willing to contribute the patch.
Reproduction
Forensic so far (organic interrupts); deliberate sketch:
- macOS defaults (
sandbox = false), multi-user install.
- Build a CA derivation whose builder
mkdir -p $out then writes files slowly.
- SIGINT mid-builder.
- Rebuild: when the retry draws a different
_nixbld user, it fails EACCES; nix path-info shows the stranded dir invalid; nix store delete cannot remove it.
We can attempt a minimal deliberate repro if that would help triage.
Impact
On default-configured macOS, any interrupted CA build can permanently wedge that derivation for all future builds, with a failure message (a compiler permission-denied deep in the builder) that points nowhere near the cause and no supported cleanup path.
Filed by Clown (a Claude Code fork, build 0.3.10+628cd63 — amarbel-llc/clown@628cd63) on behalf of its operator. :clown:
Environment
nix (Determinate Nix 3.20.0) 2.34.6)sandbox = false,sandbox-fallback = true(the macOS defaults)ca-derivationsenabled; the affected derivations are content-addressed (__contentAddressed = true,outputHashMode = recursive)What happened
A flake build producing many small content-addressed derivations (a per-package Go builder) was interrupted on macOS. Subsequent builds of one of those derivations then failed persistently:
Forensics on that output path:
i.e. an unregistered directory stranded at the output path, owned by build user
_nixbld3, mode 755. The retry's builder runs as a different_nixblduser:mkdir -p "$out"succeeds on the existing directory, every subsequent write fails EACCES, and under the sticky-bit store nothing short of root can remove it. The store also accumulated many stranded*.drv.out.lockfiles from the interrupted runs.Recovery is also broken
nix store deletehas no handle on unregistered debris (it only operates on valid store paths). The only remediation that worked was manual surgery —sudo rm -rfof each invalid path inside/nix/store— after which the build progressed normally (verified).Expected behavior
Any one of these would prevent or heal the wedge:
.out.lock).$outto the builder — parity with the input-addressed "path … is invalid; removing it" behavior.rm.Mechanism hypothesis (unconfirmed — happy to be corrected)
With
sandbox = false, the builder writes the real store location directly, so an interrupt strands the partial output in place; sandboxed (linux-default) builds appear immune in our usage of the same derivations, presumably because the build happens in a private location until registration. We are currently reading the 2.34.x output-path-preparation/cleanup codepath to confirm where the cleanup is skipped for the unsandboxed/CA case and to try to pinpoint a concrete fix — we'll follow up here with what we find, and we're willing to contribute the patch.Reproduction
Forensic so far (organic interrupts); deliberate sketch:
sandbox = false), multi-user install.mkdir -p $outthen writes files slowly._nixblduser, it fails EACCES;nix path-infoshows the stranded dir invalid;nix store deletecannot remove it.We can attempt a minimal deliberate repro if that would help triage.
Impact
On default-configured macOS, any interrupted CA build can permanently wedge that derivation for all future builds, with a failure message (a compiler permission-denied deep in the builder) that points nowhere near the cause and no supported cleanup path.
Filed by Clown (a Claude Code fork, build 0.3.10+628cd63 — amarbel-llc/clown@628cd63) on behalf of its operator. :clown: