Too Many Levels of Linking in `zsh`
One unexpected error that I have been receiving when sourcing a configuration script in zsh
(e.g. source .muttrc
) is “too many levels of linking
”.
That stumped me for some time. I eventually figured out that the issue had to do with using variables when symbolically linking those config scripts.
Let me explain.
Like most people these days I work on several computers. In my case they are all macOS/Darwin machines. Hence I need to sync most of my configuration scripts across those machines to make my environments familiar, and maintain my multitude of key bindings, when I move from one to the other.
Many people use Github for this purpose, but since I do not have any cross-platform requirements, the simplest was to build it off the built-in iCloud sync’ing capabilities of my machines. Plus it is secure.
So the first thing I did was to use zsh
’s built in “dot directory” variable, $ZDOTDIR
. In order to accommodate launching zsh
as an interactive but not login shell, e.g. launching it from within a bash
shell, I decided to use .zshenv
to define $ZDOTDIR
(although .zshrc
would work):
% cat ~/.zshenv
ZDOTDIR=$HOME/Documents/dotfiles
Notice I am already using an environmental variable $HOME
in the definition of another environmental variable $ZDOTDIR
Now, the “Documents” directory in macOS is synchronized to iCloud (if you enable it), so any config scripts that live in the dotfiles
subdirectory would sync to all of my Darwin machines.
But now, when I symbolically link a config script in that dotfile
directory to where an executing program or shell expects it to go, e.g.:
% ln -s $ZDOTDIR/muttrc $HOME/.muttrc
the symbolic link is created with no issues, however, I get the “too many levels of linking
” error when trying to launch that program later.
It took me some time to get to the bottom of this, since my config files are full of variables that could potentially cause that problem. So to save you countless hours of troubleshooting, I am giving you the solution: just don’t use the $ZDOTDIR
variable when creating the link:
% ln -s ~/Documents/dotfiles/muttrc $HOME/.muttrc
Alternatively, use the explicit path when defining $ZDOTDIR
in the first place.
I haven’t yet experimented whether using the system-wide tilde ~
alias in place of $HOME
in the $ZDOTDIR
definition would also work.
Note to self: see if this is also an issue in bash
.