Post

Debugging a problem with my fish shell.

Recently I made the switch on all my devies to use the great fish shell. It was amazing since it remembered all the commands I executed previously, was fast as bash and had inline completion.

However, one problem appeared and was bothering me too much. I need to use poetry for some projects at work, and everything worked great while I was using it in bash, whoever, when I made the switch to fish, all of the sudden poetry stopped working for me.

That seems a bit odd since it was working with bash previously without problems. Where should we look first to understand the problem?

If you never experienced this before, well, fish can’t really handle ~ in paths for your $PATH variable.

While digging this and talking with Sam Doran, which is a colleague from my team at Red Hat, we discovered that the problem was in fish handling ‘~’ in the $PATH environment variable by simply testing the following:

Take a look at the following test he conducted with me:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
> env -v -i PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin  HOME=$HOME TERM=$TERM /bin/bash

#env clearing environ
#env setenv:	PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
#env setenv:	HOME=/Users/$USER
#env setenv:	TERM=xterm-256color
#env executing:	/bin/bash
#env    arg[0]=	'/bin/bash'

bash-3.2$
bash-3.2$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

bash-3.2$ export PATH='~/bin':"$PATH"

bash-3.2$ echo $PATH
~/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

bash-3.2$ command -v simple.sh
/Users/$USER/bin/simple.sh

bash-3.2$ simple.sh
Running a simple script

and

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
> env -v -i PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin SHELL=$SHELL HOME=$HOME TERM=$TERM /opt/homebrew/bin/fish -l
#env clearing environ
#env setenv:	PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
#env setenv:	SHELL=/opt/homebrew/bin/fish
#env setenv:	HOME=/Users/$USER
#env setenv:	TERM=xterm-256color
#env executing:	/opt/homebrew/bin/fish
#env    arg[0]=	'/opt/homebrew/bin/fish'
#env    arg[1]=	'-l'
$USER@rhmbp-2021 ~>
$USER@rhmbp-2021 ~> set -x PATH /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin

$USER@rhmbp-2021 ~> echo $PATH
/usr/local/bin /usr/bin /bin /usr/sbin /sbin

$USER@rhmbp-2021 ~> set -x PATH '~/bin' $PATH
$USER@rhmbp-2021 ~> echo $PATH
~/bin /usr/local/bin /usr/bin /bin /usr/sbin /sbin

$USER@rhmbp-2021 ~> command -v simple.sh
$USER@rhmbp-2021 ~ [127]>

Credits: Sam Doran

No matter how you tested it, fish would never recognize that you had valid binaries inside your ~/.local/bin folder (or any other folder that you had set in your $PATH that starts with ‘~’).

The reason behind this is really simple. fish does not expand the $PATH variables when it has ‘~’ in it1. If you want fish to recognize your path where you install your binaries, you have to either use the full path in it, like:

1
export $PATH="$PATH:/home/$USER/.local/bin"

or, you can use the following fish snippet to add the folder to the fish_user_paths global variable.

1
set -U fish_user_paths ~/.local/bin

And it got reported/covered in here https://github.com/fish-shell/fish-shell/issues/7568#issuecomment-749200158.

References

This post is licensed under CC BY 4.0 by the author.