Repository navigation
fix(nix): retry nix commands that fail with transient network errors - #2995
Conversation
Nix retries failed downloads, but not tarballs that get cut off while being unpacked, and it gives up on server errors after a few quick attempts. A single truncated nixpkgs download failed the nightly cli-tests (test-nix-versions, macOS, Nix 2.30.2): cannot read file from tarball: Truncated tar archive detected while reading data Add Cmd.MaxAttempts (defaulted from the new Nix.MaxAttempts) so a command that fails with a known transient error (truncated/damaged tarballs, connection resets, curl receive failures and timeouts, HTTP 500/502/503/504) is re-run with a short backoff, and a one-line notice is printed. Devbox sets Default.MaxAttempts = 3. The zero value keeps today's behavior for other users of the nix package. stderr is checked from the exit error (Output), the combined output (CombinedOutput), or a tail buffer teed off a caller-provided stderr (Run, e.g. nix build). When that stderr is a terminal it's passed through untouched so Nix keeps its progress bar, so those commands aren't retried. Commands with non-file stdin aren't retried either, because the first attempt may have consumed it. GitHub rate limits and DNS failures are deliberately not retried because they won't clear within seconds. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
@claude ptal |
|
Claude finished @mikeland73's task in 27s —— View job Review of #2995: retry transient nix errorsI read the diff and the surrounding Points worth a look
Nits
Verdict: LGTM with the optional tightening in points 1–3. CI is still unchecked in the test plan. |
Address review feedback on the retry logic: - Only scan stdout for transient errors when it's combined with stderr (CombinedOutput), so a stdout line can't trigger a retry. - Bound tailWriter's backing array to 8 KiB by shifting old bytes out in place instead of reslicing. - Document that stdout may receive output from failed attempts and why file stdin is still considered safe to retry. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Claude finished @mikeland73's task in 16s —— View job Re-review of 2cb16e9I read the diff for 2cb16e9. I couldn't run Points 1–3 and 5 are addressed
Remaining nit
Not verified
Verdict: LGTM. The only follow-up is the optional stdout-only test above. |
Summary
In nightly run 37286584167,
test-nix-versions (macos-latest, 2.30.2)failed because a nixpkgs tarball download got cut off duringnix print-dev-env:Nix retries failed downloads, but not ones that fail partway through unpacking. Users can hit this too, not just CI, so devbox now retries these errors itself.
Changes
nix.Cmdhas a newMaxAttemptsfield, defaulted from the newnix.Nix.MaxAttempts. If a command fails and its stderr matches a known transient error, devbox re-runs it with a short backoff (2s, then 4s) and prints one line explaining why. The transient errors are:Failure when receiving data from the peerandTimeout was reachedHTTP error 500/502/503/504Default.MaxAttempts = 3ininternal/nix. The zero value keeps today's behavior for other users of the publicnixpackage.Output: the exit error, which coversprint-dev-env,eval,path-info, and similar.CombinedOutput: the combined output.Runwith a caller-provided stderr, likenix build: the last 8 KiB, copied off as it streams to the caller's writer.nix buildwon't retry, butprint-dev-envwill. Non-TTY environments like CI retry both.Test plan
nix/command_test.gouse a fakenixscript and cover:Output,CombinedOutput, andRunwith a teed stderrMaxAttemptsgo test -race ./nix/,go test ./internal/nix/..., andgolangci-lintall passdevbox installanddevbox runagainst real Nix with a locally built binary, with stderr piped so the teed path ran🤖 Generated with Claude Code