Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VS Code with NVM #1895

Closed
anseki opened this issue Jan 9, 2016 · 35 comments
Closed

VS Code with NVM #1895

anseki opened this issue Jan 9, 2016 · 35 comments
Assignees
Labels
bug Issue identified by VS Code Team member as probable bug verified Verification succeeded
Milestone

Comments

@anseki
Copy link

anseki commented Jan 9, 2016

Hi, thank you for great app.

So, I hope VS Code sets specified environment variables when it starts.
I use a NodeJS Version Manager such as nvm, then a path to NodeJS is not added to PATH until nvm do it. (Also NODE_PATH, NODE_HOME, etc.)
That is, CLI of modules such as Gulp, Grunt, UglifyJS, etc. are not work as Task of VS Code. (VS Code can't find out these.)

When I add to PATH a path to these CLIs such as /path/to/nvm/v4.2.4 and call code command, these Tasks work fine. Or when I add a following line to VS Code DIRECTORY/bin/code.js.

process.env['PATH'] += require('path').delimiter + '/path/to/nvm/v4.2.4';

But, When VS Code is started from launcher such as Windows Start Menu, these are not work because Code.exe is called directly.

As everyone knows, NodeJS is updated frequently. A better solution I think is that VS Code sets environment variables written in settings.json that was specified by user. Or user is given a chance such as "Startup Script(or Command)" to do something.

@joaomoreno joaomoreno self-assigned this Jan 11, 2016
@joaomoreno joaomoreno added the bug Issue identified by VS Code Team member as probable bug label Jan 11, 2016
@joaomoreno joaomoreno added this to the Backlog milestone Jan 11, 2016
@joaomoreno
Copy link
Member

This should only happen on Windows. Other OSs work properly.

@anseki
Copy link
Author

anseki commented Jan 11, 2016

This issue occurred in Ubuntu also.
I think that it occurs regardless of which OS.
Paths to node and CLI commands such as gulp are not added to PATH until nvm do it. VS Code can't find out these.

@joaomoreno
Copy link
Member

Code does find these in Linux and OS X. Please try it one more time in Linux and confirm that it doesn't work. If that's the case, it's a separate issue.

@anseki
Copy link
Author

anseki commented Jan 11, 2016

Yes, I confirmed it again, and I got same result.
For example, I did Tasks: Run Task, and VS Code said "Gulp is not installed on your system".
Of course Gulp is already installed.

I think that getUserEnvironment() makes the process take over environment variables from parent process.
But path to Gulp is not added to PATH yet. VS Code can't find out these because PATH does not include Gulp.
The cause of this issue is unrelated to getUserEnvironment(). The cause is that necessary paths are not added to PATH when VS Code starts.

@joaomoreno
Copy link
Member

getUserEnvironment() exists for the specific purpose that Code cannot rely on inheriting the environment from its parent process. It spawns a shell and reads the environment from it.

In Linux, what do you get when you run $SHELL -ilc env? This should print out the correct PATH, one that points to gulp.

@anseki
Copy link
Author

anseki commented Jan 12, 2016

Ok, I checked PATH again:

starman@blue3:~$ $SHELL -ilc env
  :
  :
SHELL=/bin/bash
  :
  :
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
  :
  :
NVM_NODEJS_ORG_MIRROR=https://nodejs.org/dist
NVM_IOJS_ORG_MIRROR=https://iojs.org/dist
  :
  :
starman@blue3:~$ printenv PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
starman@blue3:~$ echo $0
/bin/bash

Of course PATH does not include a path to Gulp, as I said repeatedly. Because Node Version Manager such as nvm adds these paths to the PATH. It in Windows also do the same.

starman@blue3:~$ nvm use v4.2.1
Now using node v4.2.1 (npm v2.14.7)
starman@blue3:~$ gulp -v
[18:06:56] CLI version 3.9.0
starman@blue3:~$ printenv PATH
/home/starman/.nvm/versions/node/v4.2.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

gulp -v above works correctly because the PATH includes /home/starman/.nvm/versions/node/v4.2.1/bin that includes gulp after nvm use.
We can avoid this issue temporarily in Windows rather than Linux, by using bin/code.js (in some cases).

So, the point of this issue is NOT that these paths are not already added to PATH, it is that we have no way to do it when VS Code starts. For example, VS Code sets environment variables a user specified when it starts, or it gives a chance such as "Startup Script(or Command)" to do something. (This Startup Script(or Command) makes nvm run, or it adds these paths to PATH.)
#1895 (comment)

@joaomoreno
Copy link
Member

Now here's what I don't understand. getUserEnvironment() was implemented to fix exactly this issue. By calling $SHELL -ilc env, it should've picked up .bash_profile or .bashrc which contains the call to nvm, which would set the variables correctly. I can confirm that works because I also use nvm every day on OS X. It works for me. And many others.

We just have to figure out what is different in your system that makes it not work. Where did nvm configure itself in your system? .bash_profile, .bashrc, some other config file?

@anseki
Copy link
Author

anseki commented Jan 12, 2016

Yes, .bashrc loads nvm in my system. And it seems that nvm.sh was done correctly.

I think that you might set nvm alias default before?, or you wrote .nvmrc?
That is, in your system, the paths were already added to PATH before you run nvm use, right? nvm use was already called automatically in some way.

Anyway, nvm default is not set in my system, and nvm use doesn't run automatically in my system. Also, some managers such as nvmw (for Windows) do not have an option that makes it run automatically, as default.

The paths may be already added to PATH when VS Code runs if a manager was called automatically in some way, otherwise these are not.

@anseki
Copy link
Author

anseki commented Jan 12, 2016

Maybe, does your system have a default node? (node that was installed without nvm)

@joaomoreno
Copy link
Member

I see. So, when you spawn a shell in your system you don't have a node in the PATH? You always need to run nvm use every time you want to use Node?

@anseki
Copy link
Author

anseki commented Jan 12, 2016

In some cases, Yes.
In a machine I everyday use, I configured the "auto-run" version manager. In others, for example, I was using nvmw before, but nvmw has some issues for me, then I removed the setting for auto-run. (nvmw doesn't support auto-run itself, then I used "startup" of Windows.) Also, In another machine (Ubuntu), I didn't configure auto-run because I used it to compile some versions of node.
Maybe I think that cases that the auto-run is not used are not uncommon, because this option of many managers is turned off as default. And node is updated frequently.

@joaomoreno
Copy link
Member

Got it. I argue your situation doesn't happen often. People usually either have node installed globally or just have a default node set up in nvm. I suggest you do the same.

An environment variable setup in settings.json wouldn't work for your, since you want to add to the PATH variable, not set it. A startup script could work, but you can always achieve that outside of vscode by doing nvm use 0.12 ; code.

Another alternative would be to use a specific node as the task command and point it to the gulp or grunt entrypoints inside the node_modules folder.

@anseki
Copy link
Author

anseki commented Jan 13, 2016

Ok.
I made a shell script that sets PATH and calls code, and I am using it instead of code.
I think that this is safety way to avoid using node of involuntary version.

So, my English is very poor. I couldn't explain well, but you interacted very patiently and kindly. Thank you 😃

@joaomoreno
Copy link
Member

Thanks for your ideas and feedback!

@vprasanth
Copy link

I'm still a little bit confused by the resolution here. Are you saying users that use nvm must launch VS Code via the terminal in order to have it use the nvm version of node? This is currently the way I have to launch VS Code on OSX to have it use the nvm version.

@joaomoreno
Copy link
Member

@vprasanth, no. @anseki seems to not have a default alias in nvm. You are maybe in the same position. You should run nvm alias default node to set up a default. It should work then.

@anseki
Copy link
Author

anseki commented Feb 24, 2016

Hi @vprasanth,
If you use a version manager that doesn't support default version such as Windows nvm, as you said, you must call nvm in a terminal before you start VS Code.
But if you use a version manager that supports default version, as @joaomoreno said, you can set default version to start VS Code without calling nvm. And I think that you use that on OSX.

@vprasanth
Copy link

@joaomoreno @anseki sweet thanks! I didn't even know I could do that. I was using nvm use xxxx within my bash_profile. Thanks!

@joaomoreno joaomoreno added the verified Verification succeeded label Apr 29, 2016
@petebacondarwin
Copy link

petebacondarwin commented Sep 21, 2016

@joaomoreno - It would be great if VS Code ran nvm use before running a node script. This allows each project to specify the version of node to use for that project, via a .nvmrc file.

@joaomoreno
Copy link
Member

joaomoreno commented Sep 21, 2016

What do you mean by running a node script? Where does this happen?

@petebacondarwin
Copy link

All of the tools, Gulp, Grunt, UglifyJS, mentioned by the OP in this issue are node.js scripts.
In particular when launching a task to run one of these tools, from VS Code, the editor must be running them via an instance of the node.js runtime.

Since there is now a range of node.js runtime versions available with breaking changes between them, different projects that I work on use different versions. NVM as a tool is great for selecting a version for a particular project, and with the .nvmrc file NVM can automatically set the necessary version by simply running nvm use (i.e. not specifying a version).

So for a concrete example, in the launch.json debug configuration file, I might have

  "configurations": [
    {
      "name": "Protractor",
      "type": "node",
      "request": "launch",
      "program": "${workspaceRoot}/node_modules/protractor/bin/protractor",
      "stopOnEntry": true,
      "args": ["protractor.conf.js"],
      "cwd": "${workspaceRoot}",
      "preLaunchTask": null,
      "runtimeExecutable": null,
      "runtimeArgs": [
        "--nolazy"
      ],
      "env": {
        "NODE_ENV": "development"
      },
      "console": "internalConsole",
      "sourceMaps": true,
      "outDir": null
    }
]

The protractor tool is a node.js script that will currently be run under the default installation of node.js on the system. But if this project requires a different version of node in order to run the protractor script it is stuffed.

Does that make sense?

@joaomoreno
Copy link
Member

Here's how you can do it, at least for debugging:

  1. Change runtimeExecutable in your debug configuration to ${workspaceRoot}/node.sh.
  2. Create a node.sh executable file at the root of your workspace with the following contents (adapt to your own shell):
#!/bin/zsh
source ~/.zshrc
nvm run $*

It isn't a great experience, but we don't want to hardcode the notion of nvm into Code. You could maybe convince the vscode-node-debug extension to do so, though.

@petebacondarwin
Copy link

@joaomoreno thanks for the workaround. I'll take a look at the node-debug extension people.

@theetrain
Copy link

This issue also affects me. On Ubuntu 16.04 using nvm, I use a node module that checks for /usr/bin/env node, but that doesn't get called properly within VSC, though it works fine in terminal when I run which node since it is properly configured in my $PATH.

Would it be possible to add a custom path to VSC's user settings? We currently have:

"git.path": null,
"php.validate.executablePath": null,

Perhaps it would help to add a custom path for node that way it gets called properly.

@anseki
Copy link
Author

anseki commented Oct 27, 2016

Hi @theetrain,

For your information, this is my solution:
I use a shell script that sets environment and starts VS Code.
Since Node.js uses some variables other than PATH, it sets these also:

  • NODE_HOME : The path to directory that contains node
  • NODE_PATH : NPM global node_modules directory (e.g. npm root -g)

@SanthoshSasi
Copy link

SanthoshSasi commented Mar 28, 2017

Or you could execute this before opening vs code
Eg:
nvm alias node v4.8.1
nvm alias node v6.10.1

@sandy-adi
Copy link

The following worked for me too:

$ nvm use <node_version>
$ code

It would be nice if there is an easier way to switch node versions while you are in the IDE.

@seanfisher
Copy link

The workaround by @joaomoreno worked well for me. I was using bash instead of zsh so I posted the updated script and details over on my blog: NVM and VS Code for anyone who's interested.

@weinand
Copy link
Contributor

weinand commented Apr 26, 2017

After reading this, I got the impression that it would make sense to add "nvm" support to node-debug. So something like "nvm": "6.5".
I've created this feature request.

@biddster
Copy link

biddster commented Jun 15, 2017

The above approach (nvm use then launch code) worked nicely for me too.

I've also being specifying the node executable too for the times that I forget to launch code via a terminal. For example:

        {
            "type": "node",
            "request": "launch",
            "name": "generator scribble",
            "runtimeExecutable": "${env:HOME}/.nvm/versions/node/v4.6.1/bin/node",
            "program": "${workspaceRoot}/generators/index.js"
        }

@jppradhan
Copy link

Thanks @biddster
"runtimeExecutable": "${env:HOME}/.nvm/versions/node/v4.6.1/bin/node", worked for me.

@vviikk
Copy link

vviikk commented Aug 7, 2017

Thanks @biddster

I just went into my command line, did a which node to give me my nvm's node location and used that path. For now, I'm very happy.

@gberdzenishvili
Copy link

gberdzenishvili commented Aug 28, 2017

(Sorry guys, pretty long discussion, maybe I missed the answer to my question)

My environment:

  • I have nvm installed (Arch Linux)
  • I have nvm sourced from .bashrc: source /usr/share/nvm/init-nvm.sh (.bash_profile sources .bashrc)
  • Node can be found in PATH
  • I configured its default: nvm alias default node
  • I do not have global node
  • Visual Studio Code 1.15.1

So when I run my Node.js project in debug mode in Visual Studio Code (Code was opened via icon) I get an error "Cannot find runtime 'node' on PATH. Make sure to have 'node' installed.". I checked process.env in developer tools and there is no nvm mention. While integrated terminal knows node command and has correct env. variables.

But when I run Code from terminal it works fine and process.env has all nvm related stuff.

Not sure if I should create a separate issue as there were many issues on this topic but I can not find a clear answer why Code running from GUI does not set nvm variables correctly.

Thank you.

@brandon14
Copy link

Similar issues to @gg-berdzenishvili. I have Linux Mint 18.2 with bash. nvm is sourced in ~/.bashrc but when launching code from the menu or desktop, any extension that relies on node doesn't function correctly such as flow-for-vscode will show an error that node cannot be found in the path.

As others have said, I'm sure I could hack around and make a shell script to set the env variables and then launch code, but I feel this is something one would expect to work out of the box. With the large number of people using nvm to manage node installs, it may be worth it to better the support for nvm out of the box.

@papandreou
Copy link

I found a way to use nvm-exec to override the default node.js version with the one specified in the project's .nvmrc: #16173 (comment)

@vscodebot vscodebot bot locked and limited conversation to collaborators Nov 17, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Issue identified by VS Code Team member as probable bug verified Verification succeeded
Projects
None yet
Development

No branches or pull requests