-
-
Notifications
You must be signed in to change notification settings - Fork 453
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
$PATH is broken for fish shell #122
Comments
Also hitting this after updating from a version from last week. Haven't narrowed down the issue, yet, but it seems like |
The same thing happens for all shells so I'm not sure what the issue is. |
I spent some time looking for this bug and wanted to post a small update, even though I have not found the source of the problem nor a solution … I went through all the commits since October and could not find anything that looked particularly problematic with regards to this problem. The one commit that caught my eye (and that I mentioned in the initial post), introduced this:
This seems suspect to me because it introduces a global env variable that might be unpredictable. But then I went into the generated I also changed the tests to test for the sequence of the Nix paths and then the system paths in order and that was also correct. But whenever I start a shell in the newest nix-darwin, my A last thing: if I would find a place where I think it goes wrong, how would I test this on my system? Would I have to build the installer and run that from my local repo? |
For the record, I'm having similar issues, it looks like. |
I'm not a fish user so I don't know what to look for but I'd take a look at NixOS/nixpkgs#45784.
|
Here are my pinned nixpkgs and nix-darwin: {
"owner": "NixOS",
"repo": "nixpkgs-channels",
"branch": "nixpkgs-18.09-darwin",
"rev": "0b471f71fada5f1d9bb31037a5dfb1faa83134ba",
"sha256": "148vh3602ckm1vbqgs07fxwpdla62h37wspgy0bkcycqdavh7ra5"
} {
"owner": "LnL7",
"repo": "nix-darwin",
"branch": "master",
"rev": "629fa534988b7a402f4278c9445f0e20e5f03973",
"sha256": "033xwz0gaqc89khbs1l3lxii5v54sqqyzag55xjyqrmaz7bbancy"
} and the resulting
For me, it looks like it's just |
I had a look at this, and I think the problem is that Fish on nix-darwin runs its initializers in an incompatible order. On macOS, there's a
Logging the startup of a fish shell (without
Nixpkgs does some additional configuration of fish to setup the environment very early, even before any of fish's main configuration is applied. Nix-darwin uses this same setup to inject the PATH variable. The eventual result is that the PATH is applied, then fish re-orders it in it's A possible solution would be to stash the initial value of While we're here: child shellsThe behaviour around Fish also makes the questionable choice of running their path_helper on all shells. This is a departure from macOS, which only runs in login shells via [1] Presently |
I think the required configuration point is missing in fish. I've filed an issue upstream at fish-shell/fish-shell#5641. |
Thanks for the research, @thefloweringash. This rabbit hole gets deeper and deeper 😓 … |
I ended up doing this: for p in /run/current-system/sw/bin ~/bin
if not contains $p $fish_user_paths
set -g fish_user_paths $p $fish_user_paths
end
end ... in my 🤷♂️ YMMV
|
Thanks for the pointer, @yurrriq, this works for me, too. I'm on fish 3.0.0 and without this I still had the problem. It's hackish, but it works … This is what I added to my
|
If that also works for the version of fish in 18.09 something similar could be added to the module by default. |
I'm using 18.09 (NixOS/nixpkgs@46d3867) on NixOS and it seems to work for fish 2.7.1 too. |
I also ran into this. Fish version 3.0.2. @yurrriq's fix works for me, as well. |
I have the following function definition in function __nix_darwin_fish_macos_fix_path -d "reorder path prioritizing darwin-nix paths"
# Fish initialization for login shells rebuilds $PATH by emulating calling /usr/libexec/path_helper
# which results in nix-darwin additional paths being appended (instead of prependd) to $PATH
# (see https://github.com/fish-shell/fish-shell/blob/90547a861a13806cdfcf479e279527b2cb18c922/share/config.fish#L171)
# As a workaround we re-source the nix-darwin environment again if necessary
if test $PATH[1] = '/usr/local/bin'
set fish_function_path ${pkgs.fish-foreign-env}/share/fish-foreign-env/functions $fish_function_path
# source the NixOS environment config again
fenv source ${config.system.build.setEnvironment}
set -e fish_function_path[1]
end
end
''; then I just invoke The first test in the function may need to be adapted though. HTH |
Here's a couple of suggestions for solutions from faho on fish-shell/fish-shell#7142 (comment)
I'm not sure which of these (if any) is most viable. |
For me a simple fix was setting |
Seeing this same problem with zsh |
We should be able to stuff the Nix stuff into {
fish = super.fish.override {
fishEnvPreInit = sourceBash: ''
set -l oldPath $PATH
'' + sourceBash profilePath + ''
for elt in $PATH
if not contains -- $elt $oldPath
set -ag fish_user_paths $elt
end
end
set PATH $oldPath
'';
};
} It records the Perhaps the best action here is to add it to And by doing it this way, the |
I just tested this by hacking my config file with |
Here's my hack: { config, lib, ... }:
with lib;
let
cfg = config.programs.fish;
in
{
config = mkIf cfg.enable {
environment.etc."fish/nixos-env-preinit.fish".text = mkMerge [
(mkBefore ''
set -l oldPath $PATH
'')
(mkAfter ''
for elt in $PATH
if not contains -- $elt $oldPath /usr/local/bin /usr/bin /bin /usr/sbin /sbin
set -ag fish_user_paths $elt
end
end
set -el oldPath
'')
];
};
} My resulting |
This is a workaround for macOS's path_helper stuff in /etc/zprofile: - NixOS/nix#4169 - LnL7/nix-darwin#122
Here's another hack that increases compatibility a bit in certain cases (like login shells): environment.etc."paths" = {
text = concatStringsSep "\n" ([ "/Users/winter/.nix-profile/bin" ] ++ (remove "$HOME/.nix-profile/bin" (splitString ":" config.environment.systemPath)));
knownSha256Hashes = [
"cdfc5a48233b2f44bc18da0cf5e26df47e9424820793d53886aa175dfbca7896"
];
}; Obviously only works for single user systems, replace |
In https://github.com/fish-shell/fish-shell/blob/e066715127fc0a515e7a8c66a2b7b21531bd500e/share/config.fish#L199 I think this change is needed: # Merge in any existing path elements
for existing_entry in $$argv[1]
if not contains -- $existing_entry $result
- set -a result $existing_entry
+ set -p result $existing_entry
end
end When I hacked this into my file in /nix/store, the resulting path was ; echo $PATH
/nix/var/nix/profiles/default/bin /run/current-system/sw/bin /Users/jelle/.nix-profile/bin /usr/local/bin /usr/bin /bin /usr/sbin /sbin /Library/Apple/usr/bin /Applications/VMware Fusion Tech Preview.app/Contents/Public /usr/local/MacGPG2/bin which seems like it's completely correct. |
@pingiun That reverses the order of the existing entries. Also this code here is mimicking the behavior of This issue affects nested The discussion in fish-shell/fish-shell#7142 (thank you @anka-213) goes into detail about the problem here. I just commented as I think a real solution does unfortunately require modifying Until such time as we get an upstream change in Fish, I think our only real solution is to patch |
Hmm, perhaps it's something that Home Manager is doing. |
Right, the installer will update fish config files in place. That is, this'll only work if you have previously installed fish and did not wipe its config files. Considering that macOS doesn't come with fish, and if you intend to use nix as a replacement for homebrew/macports, i.e. if you are gonna install fish with nix, then you need to be on nix 2.11.1 to be able to source the new nix profile scripts for fish, which are generated when building nix. If you've upgraded (downgraded) nix after a fresh install, you can switch back to the 2.11.1 generation with |
If you have nix 2.11.1 or later installed in your user profile (via This won't add paths for system installed packages--which is absolutely needed. Unfortunately, you need to add So, nix 2.11.1 is still broken with fish on Darwin. To patch this, I added this to the top of my
I included the test for Darwin as this only occurs on my darwin systems. nixos + fish paths are set just fine. |
I've encountered this too - just on the stock zsh
|
On my new MacBook it unfortunately doesn't work anymore, so I'm back to this workaround |
Fresh install of nix and nix-darwin and this worked for fixing it for me. Thanks :) |
This is a quick recap of this issue for people without much experience with Nix internals (like me!), people that don't want to read the thread, or people that just want a solid solution. What's the problem?The script nixos-env-preinit.fish is executed on shell startup. You can find this at However, this happens before fish runs its own config scripts. Only when Fish is set as your login shell, it reads from What paths exactly need to be moved?Before Fish clobbers the path variable, the important directories in it are the ... but anything can add to this value. Using hardcoded paths is probably fine but isn't completely "correct" in the programmer-y ideology kind of way. What's the fix?The paths in This module works correctly -- you can copy/paste it or save it as a file and add it to { lib, config, ... }:
{
programs.fish.loginShellInit =
let
# This naive quoting is good enough in this case. There shouldn't be any
# double quotes in the input string, and it needs to be double quoted in case
# it contains a space (which is unlikely!)
dquote = str: "\"" + str + "\"";
makeBinPathList = map (path: path + "/bin");
in ''
fish_add_path --move --prepend --path ${lib.concatMapStringsSep " " dquote (makeBinPathList config.environment.profiles)}
set fish_user_paths $fish_user_paths
'';
} You can probably get away without double quoting at all, it just makes me a little uncomfortable to think that a stray space could blow up my shell init 😅 The (There are lots of valid ways of doing this -- another is to use This is valid either in your home-manager config or nix-darwin config, both define A note about Fish's weird source orderFish is kinda weird about what order to source things in. This will be fixed in the future by sourcing config snippets (conf.d/*.fish) in order of name, regardless of the directory. So the most correct thing to do would be using something like environment.etc."fish/conf.d/00-nix.fish".text =
let
# ...
in ''
if status is-login
# config snippet...
end
''; But again, this doesn't really matter that much right now, because files under There's also the issue that fish doesn't technically source /etc/fish/..., it looks in To fix this, maybe it's worth changing nixpkgs' fish preinit to add |
@clo4 note that if you plan on using this in a home-manager managed fish shell, you'll need to use |
This helped me when I transitioned to using home-manager configs for my shell on my macbook. Thanks. |
This helps placing the nix paths in front of the $PATH variable, so that they are preferred over macos-provided or homebrew stuff. See LnL7/nix-darwin#122 for a lengthy discussion.
Hey, I'm experiencing the problem with binaries installed via nix-darwin and home-manager not being present in PATH, but for me it looks like the root cause is different in my case. ContextI'm migrating an existing homebrew setup over to a flake base nix-darwin setup with home-manager. I installed nix using the Determinate Systems installer. Right after the first Root causeThe root cause seems to be that I had configured Fix
Workaround
PATH should be correct now. |
@britter The problem is In my local setup I have my own activation script that explicitly checks for and updates my user shell because of this issue (and also this code actually sets the shell to a wrapper program that basically does |
@lilyball can you point me to the documentation of I think there are two things at play here:
This is what happens on NixOS, but it doesn't seem to work on my macOS machine. Curious to understand if I made a mistake or if I just have the wrong expectations. |
nix-darwin/modules/users/default.nix Lines 41 to 49 in afe83cb
nix-darwin/modules/users/default.nix Line 137 in afe83cb
If you look at the whole activation script here you can see that it calculates a list of "created" and "deleted" users by cross-referencing the users.knownUsers list with the users.users set. For every "created" user, if users.forceRecreate is set it first deletes the user (if it exists) and then recreates it, and if that's not set then it simply skips any user that already exists (meaning it won't apply any changes to user properties).
I feel like this whole module needs to be rewritten such that it will sync changes to known users. For any user not listed in the known users list, the properties you can set effectively act as ways to notify nix-darwin as to what your current user config is, in case anything wants to reference that. For example, I use this to tell it where the home folder for my user is, so As for |
Can we merge @clo4's fix into nix-darwin, @LnL7? |
For people having issues with zsh, the following seems working for me:
|
This is the solution I’m now using, which takes into account the new XDG locations, as described in the nix manual: # FIXME: This is needed to address bug where the $PATH is re-ordered by
# the `path_helper` tool, prioritising Apple’s tools over the ones we’ve
# installed with nix.
#
# This gist explains the issue in more detail: https://gist.github.com/Linerre/f11ad4a6a934dcf01ee8415c9457e7b2
# There is also an issue open for nix-darwin: https://github.com/LnL7/nix-darwin/issues/122
programs.fish.loginShellInit =
let
# We should probably use `config.environment.profiles`, as described in
# https://github.com/LnL7/nix-darwin/issues/122#issuecomment-1659465635
# but this takes into account the new XDG paths used when the nix
# configuration has `use-xdg-base-directories` enabled. See:
# https://github.com/LnL7/nix-darwin/issues/947 for more information.
profiles = [
"/etc/profiles/per-user/$USER" # Home manager packages
"$HOME/.nix-profile"
"(set -q XDG_STATE_HOME; and echo $XDG_STATE_HOME; or echo $HOME/.local/state)/nix/profile"
"/run/current-system/sw"
"/nix/var/nix/profiles/default"
];
makeBinSearchPath =
lib.concatMapStringsSep " " (path: "${path}/bin");
in
''
# Fix path that was re-ordered by Apple's path_helper
fish_add_path --move --prepend --path ${makeBinSearchPath profiles}
set fish_user_paths $fish_user_paths
''; |
I think this should finally be fixed in Note that fish is now consistent with the handling of other shells in nix-darwin by ignoring |
I updated nix-darwin today and had to rollback to a version from October because my
$PATH
was broken (using fish shell).Before (correct):
After (broken):
The important part being that
/run/currenty-system/sw/bin
comes too late and the Nix provided binaries are not picked up correctly, resolving to/usr/bin/git
for example. I'm also not sure where all this duplication is coming from …I tried to get to the source of this error but was not able to figure it out exactly. What worked was to switch to an older generation and then to the newest generation again: in this case, the
$PATH
was set correctly. But when I exit fish shell and enter it again, the$PATH
is broken.It could be that this problem was introduced in 676ef10#diff-02a3bd02a5cdf5583b2e516a0e92d58a because the version of nix-darwin that worked for me was from 2018-10-17 and this is the major change that happened to the environment a few days later. But then maybe not because no one else has this problem?
The text was updated successfully, but these errors were encountered: