I found this error when creating a jhipster project with npm, and first trying to install the node generator-jhipster library with:
npm install -g generator-jhipster
The error detail is as follows:
[operatorfeitam@dev01 client01-app-project]$ npm install -g generator-jhipster
npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142
npm WARN deprecated har-validator@5.1.5: this library is no longer supported
npm ERR! path /usr/local/bin/jhipster
npm ERR! code EACCES
npm ERR! errno -13
npm ERR! syscall unlink
npm ERR! Error: EACCES: permission denied, unlink '/usr/local/bin/jhipster'
npm ERR! { [Error: EACCES: permission denied, unlink '/usr/local/bin/jhipster']
npm ERR! cause:
npm ERR! { Error: EACCES: permission denied, unlink '/usr/local/bin/jhipster'
npm ERR! errno: -13,
npm ERR! code: 'EACCES',
npm ERR! syscall: 'unlink',
npm ERR! path: '/usr/local/bin/jhipster' },
npm ERR! stack:
npm ERR! 'Error: EACCES: permission denied, unlink \'/usr/local/bin/jhipster\'',
npm ERR! errno: -13,
npm ERR! code: 'EACCES',
npm ERR! syscall: 'unlink',
npm ERR! path: '/usr/local/bin/jhipster' }
npm ERR!
npm ERR! The operation was rejected by your operating system.
npm ERR! It is likely you do not have the permissions to access this file as the current user
npm ERR!
npm ERR! If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator (though this is not recommended).
npm ERR! A complete log of this run can be found in:
npm ERR! /home/operatorfeitam/.npm/_logs/2020-11-22T10_17_16_979Z-debug.log
This is because the /usr/local/lib/nodes_modules directory (where global node libraries are installed by default) is root and does not have permissions by the user who ran the command with npm to install or access installed packages.
Before fixing it we confirm that it is by the above looking at the configuration that we have in node with:
npm config list
Which in my case returns to me:
[operatorfeitam@dev01 ~]$ npm config list
; cli configs
metrics-registry = "https://registry.npmjs.org/"
scope = ""
user-agent = "npm/6.9.0 node/v10.16.2 linux x64"
; node bin location = /usr/local/bin/node
; cwd = /home/operatorfeitam
; HOME = /home/operatorfeitam
; "npm config ls -l" to show all defaults.
[operatorfeitam@dev01 ~]$
We see that the location of the node binary is in the usual default folder /usr/local/bin, and that a node v10.16.2 version is used. Now we check where the global libraries are installed with the command:
npm list -g | head -1
or:
npm list -g
This command returns in my case:
[operatorfeitam@dev01 bin]$ npm list -g
/usr/local/lib
├─┬ create-react-app@2.1.8
│ ├─┬ chalk@1.1.3
│ │ ├── ansi-styles@2.2.1
│ │ ├── escape-string-regexp@1.0.5
│ │ ├─┬ has-ansi@2.0.0
│ │ │ └── ansi-regex@2.1.1
│ │ ├─┬ strip-ansi@3.0.1
│ │ │ └── ansi-regex@2.1.1 deduped
│ │ └── supports-color@2.0.0
│ ├── commander@2.18.0
│ ├─┬ cross-spawn@4.0.2
...
...
├─┬ worker-farm@1.6.0
│ └─┬ errno@0.1.7
│ └── prr@1.0.1
└─┬ write-file-atomic@2.4.2
├── graceful-fs@4.1.15 deduped
├── imurmurhash@0.1.4 deduped
└── signal-exit@3.0.2 deduped
[operatorfeitam@dev01 bin]$
Note: With the command 'npm list -g' you get on the first line this location and all the global libraries installed. The 'npm list' command gets the non-global libraries that will be installed in a subfolder named node_modules from the location you are in when you run the npm installation command.
The previous command returns that the global library installation folder named node_modules located in /usr/local/lib. And if we therefore check who owns this path /usr/local/lib/node_modules see the source of the problem: it is owned by the root user.
[operatorfeitam@dev01 lib]$ pwd
/usr/local/lib
[operatorfeitam@dev01 lib]$ ls -la
total 8
drwxr-xr-x. 4 root root 41 Sep 20 19:34 .
drwxr-xr-x. 14 root root 4096 Nov 15 2018 ..
drwxrwxrwx. 7 root root 4096 Nov 22 11:17 node_modules
drwxr-xr-x. 3 root root 26 Sep 20 19:34 python3.6
[operatorfeitam@dev01 lib]$
The "prefix" attribute of the configuration that can be seen with the command 'npm config ls -l', which displays all the default values that the 'npm config list' command does not return, is the one that specifies where the global libraries are located that is in {prefix}/lib/node_modules. And the binaries in {prefix}/bin and the man pages in {prefix}/share/man.
If we see the value of "prefix" with the command:
npm config ls -l | grep prefix
gives us back:
[operatorfeitam@dev01 lib]$ npm config ls -l | grep prefix
prefix = "/usr/local"
save-prefix = "^"
tag-version-prefix = "v"
[operatorfeitam@dev01 lib]$
That matches what we've seen before, and that we've checked for the root user's node_modules prefix/lib/node_modules.
The solution is to create a folder in the user's home, to avoid permission issues, which has the problem locating the installation of global node libraries for that user.
For this we create a hidden folder with the name .npm-usr-local (can be any name) in the user's home with the command:
mkdir ~/.npm-usr-local
Then we specify the "prefix" attribute in the node configuration with the command:
npm config set prefix '~/.npm-usr-local'
Then in the .bash_profile file in the case of CentOS or .profile or counterpart in other linux distributions we add to the PATH the bin of this created folder which is where the binaries of the global libraries will be installed:
We reload the system variables by running the following command to reload the .bash_profile:
source ~/.bash_profile
We verify that the 'npm config list' command now gives us the new value of the "prefix" attribute:
And now we can install the generator-jhipster node library:
[operatorfeitam@dev01 client01-app-project]$ npm install -g generator-jhipster
npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142
npm WARN deprecated har-validator@5.1.5: this library is no longer supported
/home/operatorfeitam/.npm-usr-local/bin/jhipster -> /home/operatorfeitam/.npm-usr-local/lib/node_modules/generator-jhipster/cli/jhipster.js
> ejs@2.7.4 postinstall /home/operatorfeitam/.npm-usr-local/lib/node_modules/generator-jhipster/node_modules/mem-fs-editor/node_modules/ejs
> node ./postinstall.js
Thank you for installing EJS: built with the Jake JavaScript build tool (https://jakejs.com/)
> spawn-sync@1.0.15 postinstall /home/operatorfeitam/.npm-usr-local/lib/node_modules/generator-jhipster/node_modules/spawn-sync
> node postinstall
> ejs@3.1.3 postinstall /home/operatorfeitam/.npm-usr-local/lib/node_modules/generator-jhipster/node_modules/ejs
> node --harmony ./postinstall.js
Thank you for installing EJS: built with the Jake JavaScript build tool (https://jakejs.com/)
+ generator-jhipster@6.10.5
added 705 packages from 479 contributors in 23.214s
[operatorfeitam@dev01 client01-app-project]$
All that remains is to run 'npm list -g' again where we will see that the new path specified in "prefix" is used with the generator-jhipster library installed and its dependencies
And if we access the .npm-user-local folder we see that it already has a bin and lib directory that has been created and that contain the libraries and binary installed previously.