EPERM on npm.commands.install #3001

Closed
coreybutler opened this Issue Dec 14, 2012 · 6 comments

Comments

Projects
None yet
3 participants

I'm currently working on a simple node CLI program that prompts a user to install a package if it isn't already installed. Due to the nature of the framework this fits into, the particular install throwing errors is attempting a global installation.

  • Testing on Windows 8
  • User account has administrative privileges

The offending code looks like:

var npm = require('npm');
npm.load({
  registry: my_npm_registry,
  global: true
},function(){
  npm.commands.install('mypkg',function(_err,data){
    if (_err){
      console.log(_err);
    } else {
     console.log('success');
    }
  });
});

The result is:

c:\Users\Corey\Documents\workspace\node_modules\npm\node_modules\lockfile\lockfile.js:26
    throw er
          ^
Error: EPERM, mkdir 'c:\Program Files\nodejs\node_modules\mypkg'

Based on this, it seems the user account doesn't have the ability to create the directory. Seeing as it isn't an EACCES error, I figure it isn't a permission issue, but more the fact it is trying to install in Program Files.

However; when I try to install by typing npm install mypkg -g, it works.

I've sort of worked around this using the following:

var exec = require('child_process').exec;

exec("npm --registry "+my_npm_registry+" install mypkg -g",function(error,out,err){
  if (error)
    console.log(error)
  else
     console.log(out);
});

The code above works. I don't understand why it would work as a child process, but not the first way. This seems like it is either a bug or I'm missing something.

Member

mfncooper commented Dec 15, 2012

Seeing as it isn't an EACCES error, I figure it isn't a permission issue

EPERM means "operation not permitted". Seems like permissions to me. :-)

Not sure if it's related, but note that your code-based install should be using the npm object provided in the callback from load. That is, your load usage should be:

npm.load({ ... }, function (err, npm) {
    // Now use the npm argument in here, not the object you had before
});

The "operation not permitted" simply means the issue is not a matter of granting elevated privileges. Some operations, even with root permissions, aren't allowed by the OS.

Good eye, and thanks for the pointer on using the callback npm object - the examples either didn't show that clearly or I simply missed it. I'll try it out and report back if that fixes the issue.

Upon further review, the npm suggestion @mfncooper mentioned appears to be unrelated. The following code works:

var npm = require('npm');
npm.load({
  registry: my_npm_registry,
  global: false
},function(){
  npm.commands.install(["mypkg"],function(_err,data){
    if (_err){
      console.log(_err);
    } else {
      console.log('success');
    }
  });
});

whereas the code below does not:

var npm = require('npm');
npm.load({
  registry: my_npm_registry,
  global: true             // <---- Key Difference
},function(){
  npm.commands.install(["mypkg"],function(_err,data){
    if (_err){
      console.log(_err);
    } else {
      console.log('success');
    }
  });
});

So, the obvious difference is the global flag. On Windows, the Program Files directory (under which the global package directory is created) is one of those special directories where even administrators typically can't install without responding to a prompt.

To me, it feels as though npm is using a different user account or not handling the Program Files directory properly when executing programmatically. That also doesn't make sense to me (thus why this is still stumping me).

busches commented Sep 26, 2016

Is this still causing an issue for you in later versions of npm? The npm prefix on Windows defaults to the C:\Users\%CurrentUser%\AppData\Roamin\npm now a days instead of Program Files and should help avoid most of your issue.

@busches - I abandoned this long ago (issue is 4yrs old), so I don't really know. However; it's not safe to assume npm will always be in the roaming profile. In nvm-windows users have a choice where it goes. I worked around it by building an admin elevation utility.

I'm going to close this since it is so old.

busches commented Sep 26, 2016

@coreybutler you're correct, I should have said it defaults to roaming currently with the node.js installer and the user can always override it in their own configuration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment