fix(nix): detect nix at known locations, not just $PATH (#2787)#2903
Open
mikeland73 wants to merge 1 commit into
Open
fix(nix): detect nix at known locations, not just $PATH (#2787)#2903mikeland73 wants to merge 1 commit into
mikeland73 wants to merge 1 commit into
Conversation
Devbox ran nix commands via resolvePath(), which searches $PATH and then
falls back to well-known install locations, invoking nix by absolute path.
But installation detection (BinaryInstalled) used a bare `exec.LookPath("nix")`
$PATH check. The two disagreed: on NixOS, or when a non-POSIX login shell such
as fish hasn't sourced the Nix profile, nix exists at a known location but
isn't on $PATH, so devbox aborted with "nix binary is not in your PATH" even
though it could have run nix fine.
- Point BinaryInstalled at the same resolver used to run nix commands, via a
new exported nix.(*Nix).LookPath / nix.LookPath.
- Fix resolvePath's fallback list: the NixOS entry was the bin *directory*
(/run/current-system/sw/bin), which the "not a directory" check always
rejected, so it never matched. It now points at the nix binary itself.
- Extract the fallback paths into nixBinaryFallbackPaths() and add a regression
test asserting each entry is an absolute path to the nix binary.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BXJuDH6keqvU1ydywuyizq
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes Nix installation detection so Devbox can proceed when nix exists at well-known locations but is not on the interactive shell’s $PATH (notably on NixOS and in shells like fish), aligning “detection” with the same resolution logic used to actually execute nix.
Changes:
- Added an exported
(*nix.Nix).LookPathmethod (andnix.LookPathhelper) so callers can resolve thenixexecutable using the same logic as command execution. - Fixed and extracted the fallback search list so the NixOS entry points to the
nixbinary (/run/current-system/sw/bin/nix) rather than the directory. - Updated
internal/nix.BinaryInstalledto use the resolver (not PATH-only checks) and added a regression test to ensure fallback entries are absolute paths to thenixbinary.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| nix/nix.go | Exposes LookPath, fixes fallback search behavior, and centralizes fallback paths. |
| nix/nix_test.go | Adds regression test ensuring fallback paths are valid absolute .../nix entries and include the NixOS location. |
| internal/nix/install.go | Updates BinaryInstalled() to rely on the shared resolver to avoid false negatives when nix isn’t on $PATH. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #2787.
Users on setups where nix is installed but not on the interactive shell's
$PATH— notably NixOS, and shells that don't source the Nix profile the way devbox expects (e.g. fish) — hit this even though nix is present and working:The root cause is that devbox used two different mechanisms to find nix:
nix.(*Nix).resolvePath()searches$PATHand then falls back to well-known install locations, invoking nix by absolute path. This works even when nix isn't on$PATH.BinaryInstalled()used a bareexec.LookPath("nix")— a$PATH-only check.So detection could report nix as missing and abort in
EnsureNixInstalled, even though devbox would have been perfectly able to run nix by absolute path.On top of that,
resolvePath's fallback list had a latent bug: the NixOS entry was the bin directory/run/current-system/sw/bin, but the loop only accepts a path that is a non-directory executable — so that entry could never match, and the NixOS system-profile location was effectively never searched.Fix
internal/nix/install.go:BinaryInstalled()now uses the same resolver that runs nix commands, via a new exportednix.(*Nix).LookPath/nix.LookPath. Detection and execution can no longer disagree.nix/nix.go: fix the fallback list so the NixOS entry points at the nix binary (/run/current-system/sw/bin/nix), and extract the list intonixBinaryFallbackPaths().$PATHis still found first; behavior only differs when nix is off-$PATHbut present at a known location, where devbox now proceeds instead of erroring.How was it tested?
go build ./nix/... ./internal/nix/... ./internal/boxcli/...passes.go test ./nix/...passes, including a newTestNixBinaryFallbackPathsregression test asserting every fallback entry is an absolute path to the nix binary (guarding against the directory-vs-binary bug) and that the NixOS system-profile path is covered.go test ./internal/nix/...: the added/affected tests pass. (TestConfigIsUserTrustedfails in this sandbox only because it shells out to a realnix, which isn't installed here — it fails identically on the unchanged base branch and is unrelated to this change.)cc @simulatedcode (issue reporter)
Community Contribution License
All community contributions in this pull request are licensed to the project
maintainers under the terms of the
Apache 2 License.
By creating this pull request, I represent that I have the right to license the
contributions to the project maintainers under the Apache 2 License as stated in
the
Community Contribution License.
🤖 Generated with Claude Code
https://claude.ai/code/session_01BXJuDH6keqvU1ydywuyizq
Generated by Claude Code