Skip to content

Retry the second phantom-store-path eval wording in the devenv retry wrapper (#3594) - #3595

Merged
mcdonc merged 2 commits into
mainfrom
i3594-daily-fuzz
Oct 26, 2026
Merged

mcdonc merged 2 commits into
mainfrom
i3594-daily-fuzz

Conversation

@mcdonc

@mcdonc mcdonc commented Oct 26, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes the Oct 26 daily-fuzz failure (run 40320711358): the run died 49s into shell evaluation with error: getting attributes of path "/nix/store/…-builder.pl": No such file or directory — the same per-eval coin flip retry-on-invalid-path.sh exists to absorb (#2774 / cachix/devenv#3064), but in the stat-failure wording rather than the database-miss is not valid wording the wrapper's signature matched, so the one-retry conversion never ran. Closes #3594. The #3591 bootstrap fix from the prior day is uninvolved and intact — this failure is one layer earlier (eval, before any task ran).

The wrapper now retries both phantom-missing-store-path wordings, tolerating either quote style; the ANSI strip is printf-built so it works on BSD sed as well as GNU (nix colorizes when it believes stderr is a terminal — run 40320711358's log carried raw SGR sequences between the tokens). All four consumers (devenv-setup Prepare/Build, e2e-suite, fuzz-daily Build images) get the widened match automatically.

Verification

  • New behavior tests (scripts/tests/test_retry_on_invalid_path.py, the test_podman_reexec_retry pattern) execute the real wrapper against fake commands: each wording retries once and succeeds (including an SGR-colored message), an unrelated failure passes through with its original exit code and no retry, and a signature on both attempts fails after exactly one retry.
  • Full scripts/tests: 218 passed; xenon gate passed.

Notes

  • The fuzz-daily-retry safety net correctly did not fire (it keys on the eviction signature — upload step skipped — and here the upload step ran); widening it is deliberately out of scope: a bootstrap failure should stay red, and the wrapper is where the mechanism lives.

The daily fuzz's Oct 26 scheduled run died at shell evaluation with
'error: getting attributes of path .../builder.pl: No such file or
directory' — the same per-eval coin flip the retry wrapper exists for
(#2774 / cachix/devenv#3064), in the stat-failure wording instead of
the database-miss 'is not valid' wording the wrapper matched. Both
wordings now retry once (quote-style tolerant; the ANSI strip is now
printf-built so it works on BSD sed too). Behavior tests execute the
real wrapper against fake commands: each wording retries once and
succeeds (including an SGR-colored message), unrelated failures pass
through with their original exit code, and a signature on both
attempts fails after exactly one retry.
@github-actions github-actions Bot added the backport/2.0 Merge also backports the squash commit to stable/2.0 (#3361) label Oct 26, 2026
@mcdonc

mcdonc commented Oct 26, 2026

Copy link
Copy Markdown
Owner Author

Fresh-eyes review

Investigation complete. Probes of the real wrapper (exit codes preserved in every case, retried = whether the ::warning annotation fired):

Probe Result
error: path /nix/store/abc is not valid (unquoted) rc=7, retried — widening works
error: path "/nix/store/abc" is not valid (double-quoted) rc=7, retried
error: path '/nix/store/abc' is not valid-ish rc=7, retried (substring match)
error: getting attributes of path "src/foo.py": No such file… rc=7, not retried — /nix/store anchor holds
… path /etc/passwd: No such file… rc=7, not retried
error: path '/nix/store/a is not valid (unterminated quote) rc=7, retried (opening quote independently optional)
no error: prefix not retried
signature + rc=0 rc=0, no retry
signature split across lines not retried (grep is line-based)
signature on stdout only, rc≠0 retried (pre-existing 2>&1 | tee behavior)

Regex bytes verified via od: the class is [^'"]* — no stray backslash (bash collapses \" inside double quotes). Xenon rank A on the test file; macos-smoke.yml:135 runs scripts/tests, so the BSD-sed claim is exercised on macOS (where the old \x1b pattern would fail the ANSI test). All five tests pass; bash -n clean.

Blocking issues

None found.

Important issues

None found. Specifically checked and cleared:

  • /nix/store anchor — required literally in both regexes (retry-on-invalid-path.sh:27-30); project-file and non-store stat failures pass through. Retrying those wouldn't mask anything anyway (retry-once, rc preserved), but the anchor avoids pointless double-runs.
  • False-retry risk — unchanged in kind from the old wrapper: both grep the same combined stdout+stderr log; a test binary echoing the signature still triggers one retry but the final exit code is the command's own (pinned by test_signature_on_both_attempts_fails_after_one_retry). The diff widens only the accepted wordings/quote styles, nothing about where output is scanned.
  • Portability — sed "s/$(printf '\033')\\[[0-9;]*m//g" collapses to a raw ESC byte + \[ in the pattern; equivalent on GNU sed, correct on BSD sed (which doesn't support \xHH). printf is a bash builtin; shebang is bash.

Nits / questions

  • retry-on-invalid-path.sh:52 — stripped=$(strip_ansi "$log") now runs on every failed attempt including attempt 2, where it's unused (the old short-circuit skipped it). Wasted work on a big log; harmless.
  • Overreach verified but unpinned: the quote classes are independently optional, so is not valid-ish and unterminated-quote variants match. Bounded harm; no action needed.
  • .github/actions/devenv-setup/action.yml:69-71 — the Prepare-step comment still describes only the "path ... is not valid" wording; now stale relative to the wrapper's two-wordings contract.
  • No test pins the unquoted-path widening (probed manually above: it retries). If someone later tightens the quotes to required, the suite stays green.
  • Only the first test asserts the annotation text; fine, but a shared assertion would pin the ::warning for both wordings.
  • On Linux (GNU sed) the ANSI test passes with the old \x1b pattern too — the BSD fix is only verifiable on the macos-smoke runner. Acceptable given macos-smoke runs scripts/tests.
  • Changelog correctly skipped (CI-infra only, per the skip rule); the "remove once nix 2.35 is pinned" header contract is intact.

Verdict

APPROVE — the fix is correct, tightly scoped, well-tested, and every adversarial probe either retried harmlessly or passed through with its original exit code.


The three nits (stale Prepare-step comment, lazy ANSI strip, unquoted-path test pin + annotation assertion) landed in 2c78558; 219 tests green.

@mcdonc

mcdonc commented Oct 26, 2026

Copy link
Copy Markdown
Owner Author

3D dependency graph (self-contained HTML)

The page is fully self-contained: save it from either link and it opens offline. GitHub serves the raw gist as plain text, so the source link downloads; the render link views.

@mcdonc
mcdonc merged commit 2a22455 into main Oct 26, 2026
9 of 10 checks passed
@mcdonc
mcdonc deleted the i3594-daily-fuzz branch October 26, 2026 19:16
@mcdonc

mcdonc commented Oct 26, 2026

Copy link
Copy Markdown
Owner Author

Successfully created backport PR for stable/2.0:

mcdonc added a commit that referenced this pull request Oct 26, 2026
…wrapper (#3594) (#3595) (#3596)

* Retry the second phantom-store-path eval wording (#3594)

The daily fuzz's Oct 26 scheduled run died at shell evaluation with
'error: getting attributes of path .../builder.pl: No such file or
directory' — the same per-eval coin flip the retry wrapper exists for
(#2774 / cachix/devenv#3064), in the stat-failure wording instead of
the database-miss 'is not valid' wording the wrapper matched. Both
wordings now retry once (quote-style tolerant; the ANSI strip is now
printf-built so it works on BSD sed too). Behavior tests execute the
real wrapper against fake commands: each wording retries once and
succeeds (including an SGR-colored message), unrelated failures pass
through with their original exit code, and a signature on both
attempts fails after exactly one retry.

* Review nits: lazy ANSI strip, unquoted-path pin, fresh action comment (#3594)

(cherry picked from commit 2a22455)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport/2.0 Merge also backports the squash commit to stable/2.0 (#3361)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Daily fuzz run 40320711358: nix eval dies with 'getting attributes of path builder.pl' — retry wrapper doesn't match this signature

1 participant