Neovim snap and nodejs snap connection bug?



First of all question to Canonical. Why Neovim snap cannot use NodeJS snap out of the box if they are installed in classic mode and /usr/bin/snap is in the path? As you read, you’ll notice that snaps see themselves correctly when referencing binaries directly instead of via a symlink to the snap.

For all those who use Ubuntu or another distribution but use SNAP formatted applications.

Neovim is installed in the classic form, which eliminates any problems with permissions and path access, but is it really?

We will install neovim using:

sudo snap install nvim --classic

After installation, by entering nvim we should get the neovim application start window. (Pic1)

At this stage everything works fine. It’s time to check if all configuration files are loaded correctly. For this purpose, we will create a ~/.config/nvim/init.lua file

And we will enter print(‘hello’) in it. (Pic2)

As you can see, everything works properly. Next, it’s time to install the Nodejs server, which is needed, among others: to support Language Server Protocol (e.g. pyright).

We install using:

sudo snap install node --classic

As above, snap in the classic version.

Time to test the correctness of the installation (Pic3)

As you can see, everything works properly, but is it really?

Let’s try to check the npm version (needed to install pyright) directly in the neovim application. (Pic4)

Empty! This wasn’t what we expected.

Why is this happening? This is probably the specific nature of how snap applications work. Our user has the path /snap/bin added. As you can see, everything in this path is a symbolic link that in most cases leads to /usr/bin/snap. (Pic5)

This is the specificity of how snaps work. Based on the invoked application, snap will try its best to invoke the application you are requesting. Unfortunately, I don’t know how it works exactly underneath (the code is open-source, so you can read), but such software operation causes the problems shown in image 4.

Is there a cure for this? Is!

Snaps are also physically present in the system as an unpacked snap package based on the SquashFS file system, so we have full readability. Such installed applications are located in /snap/{{package_name}} (Pic6)

By going to /snap/node/current/bin we can see that there are binary files referenced by snap using its abstraction layer. (Pic7)

It should be mentioned that “current” is a symlink and always refers to the latest version of the application, because we may have several different versions of the application installed in the system.

So what happens if we query this binary directly from within Neovim? Bingo! (Pic8)

So what do we need to do to make neovim snap and nodejs snap work properly? Nothing could be further from the truth. We need to extend our user path with another folder containing executable files.

In .profile or any other file that is sourced upon launching terminal:

export PATH=/snap/node/current/bin:$PATH

After these operations, LSP, Copilot and many others will work properly.

Then we are asking for massive trouble…

That it works on your system currently is a sheer matter of luck and based on the fact that the libraries inside the snap are version wise relatively close to the ones outside of it… one simple update can already break this.

snap apps require that they are executed through the snap command which makes sure that the correct environment and base system are set up based on their snap.yaml (as you have noticed, this is achieved through the symlink setup pointing to the snap binary)

Neovim seems to not properly inherit the environment of the user here (to find npm etc), this might be a bug in its packaging …

Why does it work with Nvim snap + apt nodejs then? Just curious, because I’m new in the snap universe and still learning.

Thanks for any answer :wink:

Moat likely because that is in the standard PATH … you could try to make a symlink from /usr/bin/npm to /snap/bin/npm… or extend the path in the neovim config somehow…

If neovim seems to not properly inherit the environment:

So how is this possible?

As far as I know the /snap/bin/ is in the default PATH in ubuntu. And additionaly if I alter the path with the path to the binary (skipping the snap wrapper) everything works properly. So I don’t get something here…