Skip to content

Interrupted build with sandbox=false strands an unregistered _nixbld-owned dir at the output path; subsequent builds fail EACCES; nix store delete cannot remove the debris #487

@friedenberg

Description

@friedenberg

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:

  1. Interrupt cleanup removes the in-progress output directory (and its .out.lock).
  2. 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.
  3. 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:

  1. macOS defaults (sandbox = false), multi-user install.
  2. Build a CA derivation whose builder mkdir -p $out then writes files slowly.
  3. SIGINT mid-builder.
  4. 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:

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions