Nix shell not shadowing existing node installation

I have the latest available node installed with home-manager. However, in order to setup github copilot, I need node <= 17. So I tried to get a shell with node 16:

⮞ node --version
v18.12.1
⮞ which node
/home/james/.nix-profile/bin/node
⮞ nix shell nixpkgs#nodejs-16_x
⮞ node --version
v18.12.1
⮞ which node
/home/james/.nix-profile/bin/node
⮞ echo $PATH
/home/james/.nix-profile/bin /home/james/.pack/bin /home/james/.npm-global/bin /nix/store/0l5yh0rdzibk8arj9c8gzy1570jkc3vf-nodejs-16.18.1/bin /home/james/.nix-profile/bin
# [... snip]
⮞ /nix/store/0l5yh0rdzibk8arj9c8gzy1570jkc3vf-nodejs-16.18.1/bin/node
Welcome to Node.js v16.18.1.
Type ".help" for more information.

It seems like the new path from the nix shell comes after my profile, so the first node found is the existing installed one, version 18.

I need neovim to see node 16, how can I get it to take priority?

Ok it seems like the problem is fish being weird:

⮞ node --version
v18.12.1
⮞ nix-shell -p nodejs-16_x

[nix-shell:~]$ node --version
v16.15.0

[nix-shell:~]$
exit
⮞ echo $PATH
/home/james/.nix-profile/bin /home/james/.nix-profile/bin /home/james/.pack/bin /home/james/.npm-global/bin /home/james/.local/bin /usr/local/bin /usr/bin /bin /usr/local/sbin /usr/lib/jvm/default/bin /usr/bin/site_perl /usr/bin/vendor_perl /usr/bin/core_perl /var/lib/snapd/snap/bin /home/james/.cabal/bin /home/james/.ghcup/bin
⮞ nix shell nixpkgs#nodejs-16_x
⮞ node --version
v18.12.1
⮞ echo $PATH
/home/james/.nix-profile/bin /home/james/.pack/bin /home/james/.npm-global/bin /nix/store/0l5yh0rdzibk8arj9c8gzy1570jkc3vf-nodejs-16.18.1/bin /home/james/.nix-profile/bin /home/james/.nix-profile/bin /home/james/.local/bin /usr/local/bin /usr/bin /bin /usr/local/sbin /usr/lib/jvm/default/bin /usr/bin/site_perl /usr/bin/vendor_perl /usr/bin/core_perl /var/lib/snapd/snap/bin /home/james/.cabal/bin /home/james/.ghcup/bin
⮞

Several paths seem to be being “re-prepended” to the path after nix has prepended its paths. Has anyone else run into this problem with fish?

What OS are you on and what configures enabling Nix in your Fish sessions (NixOS, Home Manager, Nix-Darwin, manual configuration under ~/.config/fish/conf.d/*.fish, etc.)?

Edited to add: if you have programs.fish.enable = true; written in some module system’s config file, that’s the one that’s enabling Nix support in Fish.

1 Like

I’m on Arch linux. Yup, it’s home-manager programs.fish.enable. Here’s the relevant section of common.nix (my main config)

1 Like

Hmm, I also have

⮞ cat .profile
export XDG_DATA_DIRS=$HOME/.nix-profile/share:$HOME/.share:"${XDG_DATA_DIRS:-/usr/local/share/:/usr/share/}"
export NIX_PATH=${NIX_PATH:+$NIX_PATH:}$HOME/.nix-defexpr/channels

I think that’s from before I was using home-manager, so possibly that’s not needed if I’m using programs.fish.enable? However I thought fish didn’t read .profile, so it shouldn’t affect things.

⮞ mv .profile .profile.bak
⮞ nix shell nixpkgs#nodejs-16_x
⮞ echo $PATH
/home/james/.nix-profile/bin /home/james/.pack/bin /home/james/.npm-global/bin /nix/store/0l5yh0rdzibk8arj9c8gzy1570jkc3vf-nodejs-16.18.1/bin /home/james/.nix-profile/bin /home/james/.nix-profile/bin /home/james/.local/bin /usr/local/bin /usr/bin /bin /usr/local/sbin /usr/lib/jvm/default/bin /usr/bin/site_perl /usr/bin/vendor_perl /usr/bin/core_perl /var/lib/snapd/snap/bin /home/james/.cabal/bin /home/james/.ghcup/bin

Doesn’t seem to be the issue!

It might be a Home Manager bug. In NixOS, we go to some lengths to make sure that Nixifying the environment happens before the sourcing of any config files. Some of that relies on looking at some files in /etc, which Home Manager doesn’t control, so idk what they’re doing instead.

I’m traveling atm but I’ll try to look at Home Manager’s fish module when I get a chance, since the answer is probably in there. (I’ll also see if I can repro with Home Manager on Ubuntu)

And yeah, Fish doesn’t read ~/.profile. If it was a fish config file in your user configuration, it’d be under ~/.config/fish, either in config.fish or the conf.d directory

1 Like
 tree -l ~/.config/fish
/home/james/.config/fish
├── completions
├── conf.d
│   ├── plugin-nix-env.fish -> /nix/store/z97jdjs2a4sf310545j5nnbd68kjfcag-home-manager-files/.config/fish/conf.d/plugin-nix-env.fish
│   └── plugin-nvm.fish -> /nix/store/z97jdjs2a4sf310545j5nnbd68kjfcag-home-manager-files/.config/fish/conf.d/plugin-nvm.fish
├── config.fish -> /nix/store/z97jdjs2a4sf310545j5nnbd68kjfcag-home-manager-files/.config/fish/config.fish
├── fish_variables
└── functions -> /nix/store/z97jdjs2a4sf310545j5nnbd68kjfcag-home-manager-files/.config/fish/functions
    ├── check_network.fish
    ├── feh.fish
    ├── fish_greeting.fish
    ├── flakify.fish
    ├── git_check.fish
    ├── hms.fish
    ├── mkcd.fish
    ├── ncd.fish
    ├── n.fish
    ├── pacwhy.fish
    ├── po.fish
    └── try.fish

It looks like I have a plugin installed, which I’d forgotten about: nix-env.fish. Possibly that and programs.fish.enable are mutually redundant? Let me figure out how to disable it.

1 Like

Yeah, getting rid of that seems to have solved it. Thanks for your help!

I think that’s likely how programs.fish.enable = true; is implemented. There is some other way your environment is being Nixified as well, and I do wonder what it is.

Glad you resolved your issue, though!