LSP: Could not start LSP-* due to not being able to find Node.js runtime on the PATH

This is just a guide on how to handle this issue.

If you get a popup saying: Could not start LSP-* due to not being able to find Node.js runtime on the PATH. Press the "Install Node.js" button to install Node.js automatically (note that it will be installed locally for LSP and will not affect your system otherwise).

Depending if you already have Node.js installed on your system the fix is the following:

You don’t have node installed on your system.

a) Press the Install Node.js button and LSP will automatically install the Node Runtime locally(Node V12 will be installed at the time of writing). It won’t install Node globally!

b) You manually download and install Node.js. Keep in mind that there are some servers that don’t work with specific versions of Node. (an error message will be printed in ST console(ctrl+`) if that is the case. For example LSP-intelephense: Error: Ignoring system Node.js runtime due to an error. Node.js version requirement failed. Expected minimum: 10.0.0, got 8.17.0.)

You have Node install on your system.

If you still see this popup “Could not start LSP-* due to not being able to find Node.js runtime on the PATH” but you have Node in your $PATH, that means that Sublime Text didn’t pick up your $PATH. See https://lsp.sublimetext.io/troubleshooting/#updating-the-path-used-by-lsp-servers on how to resolve this.

Feel free to make suggestions to improve this guide. 😃

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 1
  • Comments: 33 (15 by maintainers)

Most upvoted comments

This happens because for some reason the LSP developers decided to manage the installation of these tools.

You can see throughout the code base that they have class methods for storage_path and binary_path as in they expect to be managing these paths…

None of this would be a drama if instead:

  • when determining if the said tool exists, execute command $EXPECTED_BINARY_NAME from the following order: cwd of the currently open file, the root of the current folder project, where ever subl was executed from
  • remove all code that trys to manage installing the tools and instead defers to something superior like asdf-vm

Currently, all the LSP tools only work if I execute subl from the root of the project directory first.

If for some reason all the windows close (like when i logout of the desktop) and login again, launch sublime from desktop launcher, all the previously open windows (that had working scoped instances of LSP) now have broken instances of LSP because the CWD is different.

It’s pretty annoying.

Another reason why LSP and co shouldn’t be managing the installation or making assumptions about where the binaries are is that every project will use different versions of these tools (precisley the value proposition of asdf). LSP forces you to use incorrect versions of the tools across your projects.

change my mind.

It would probably be better if you wouldn’t suggest such, as you called it, “gross” solutions. There are already solutions that are clean and work so not sure why they wouldn’t for you.

ST on macOS prints something like:

environment variables loaded using: /bin/zsh -l

in its console on start. If that doesn’t error out then it does work as long as you’ve extended the PATH in the proper file (as described in LSP documentation linked in the initial comment).

I’d still recommend doing as the documentation explains and make nvm init script run from .bash_profile or .zprofile. Then you don’t need to customize all those settings and you have universal solution that works across all ST packages.

Note that modifying .bash_profile requires re-login for the changes to be picked up (on Linux at least).

Try this but in LSP-typescript settings (Preferences: LSP-typescript settings from the Command Palette).

{
    "env": {
        "PATH": "~/.nvm/current/bin"
    }
}

Fyi, if you are using ZSH with oh-my-zsh, you may only have a ~/.zshrc file and not a ~/.zprofile.

What fixed this for me was to manually create an empty ~/.zprofile file with only the bits needed to adjust thePATH, as described in the guide.

This might be a root cause of confusion for people?

To be fair it can be closed and pinned. But maybe it should be just unpinned because with a lot of confusion that is going through the comments it might be more confusing than helpful.

It’s a sticky issue to guide people.

@niksy I’m not planning on adding such option to lsp_utils. If you want to hardcode the path without using the nvm init script then it’s as easy to do that in .zprofile as it would be in a dedicated lsp_utils option. And the latter would require a lot more changes to handle that.

… I want to avoid adding Node on every shell startup, so adding it through JSON configuration is excellent choice. I was under the impression that this will be used as PATH for that particular LSP implementation. …

@niksy I have the exact same concern. I’m using nvm and none of the solutions worked for me. Adding the init as recommended to my shell rc file slows its startup time considerably:

# Taken from nvm repo (https://github.com/nvm-sh/nvm#install--update-script)
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm

Before getting into sublime, it’s important to say I had this function defined in my shell to address the slow init issue (NVM_DIR was already exported in my .profile equivalent):

# Set nvm
unalias setnvm 2>/dev/null
setnvm () {
    [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
}

Now, what fixed the issue with Sublime LSP-* for me was defining a wrapper function around subl (below the setnvm definition). Zsh users, this is my solution:

unalias subl 2>/dev/null; unset -f subl 2>/dev/null
subl() {
    if command -v nvm &>/dev/null; then
        PATH=$PATH $(whence -p subl) "$@"
    else
        setnvm
        PATH=$PATH $(whence -p subl) "$@"
    fi
}

Caveats: It probably won’t work if you open sublime through a graphical interface (like clicking on a desktop[¹] menu or files in a file manager). I use a terminal for most things, so that “half” solution is enough for me.

Bash users, you can try this on your .bashrc or equivalent. No guarantees though:

unalias setnvm 2>/dev/null
setnvm () {
    if [ -z ${NVM_DIR+x} ]; then
        export NVM_DIR="${XDG_DATA_HOME:-"$HOME/.local/share"}/nvm"
        export NVM_SYMLINK_CURRENT=true
    fi

    if [ -z ${NPM_CONFIG_USERCONFIG+x} ]; then
        export NPM_CONFIG_USERCONFIG="${XDG_CONFIG_HOME:-"$HOME/.config"}/npm/npmrc"
    fi

    [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
}

unalias subl 2>/dev/null; unset -f subl 2>/dev/null
subl() {
    if command -v nvm &>/dev/null; then
        PATH="$PATH" "$(type -P subl)" "$@"
    else
        setnvm
        PATH="$PATH" "$(type -P subl)" "$@"
    fi
}
[1]

If that’s important to you and you really found no other solution, try creating/editing the Exec= line of a sublime .desktop file (see the ones in ~/.local/share/applications for reference). I didn’t try this, and I don’t have such file for sublime, this is just a suggestion if nothing else worked.

My solution was to just add

os.environ["PATH"] = os.pathsep.join(set(os.environ["PATH"].split(os.pathsep) + ["/usr/local/bin"]))

Near the top of every *.py file containing either os.getenv("PATH") or os.environ["PATH"]. It’s heavy handed, clunky, and gross, but it worked. (sort of, now LSP doesn’t always start on open… and I cannot seem to start it manually) Prior to that I duplicated my dotfiles to the appropriate profile/rc versions.

I think the fundamental issue is that Sublime’s OS implementation is not reading the path from /etc/pass and doesn’t look for dotfiles. Can’t speak for Linux for n00b reasons, but almost everything on OSX gets linked into /usr/local/bin. You can’t add links to the places on python’s path variable with sudo, ime.

OK, I’ve tried that and indeed that doesn’t work. That’s because we try to install the node dependencies before starting the sever and that already requires node to be in the PATH (or a LSP-local one to be used).

I guess if we would want to address that case then the fix would have to be in the https://github.com/sublimelsp/lsp_utils and it would need to allow specifying your own path to the node runtime.