できない.dev

npm install が EACCES(permission denied)で失敗する

グローバル install で /usr/local や /usr/lib への書き込み権限が無いと EACCES になる。
sudo に頼らず npm の prefix をユーザー領域に張り直すか、nvm / fnm で Node 自体を入れ直すのが安全策。

公開: 更新:

要約

npm install -gEACCES: permission denied が出るのは、グローバル prefix が システム所有のディレクトリ を指しているため。sudo npm で逃げると ~/.npm の所有権が root に汚染され、後の通常 install まで巻き添えで失敗するようになる。
安全策は prefix をユーザー領域に張り直す か、nvm / fnm / volta で Node 自体をユーザー領域に入れ直す こと。

よくある原因

  1. prefix がシステム領域: npm config get prefix の出力が /usr/local など root 所有を指す
  2. sudo install の副作用: 過去に sudo npm i -g を打ち、~/.npm の所有権が root になっている
  3. OS パッケージ製の Node: apt / yum / Homebrew で入れた Node はシステム配下に書き込もうとする
  4. 共有 node_modules: 別ユーザーで作られたディレクトリに今のユーザーで書き込もうとしている

解決策

1. prefix をユーザー領域に張り直す

mkdir -p ~/.npm-global
npm config set prefix '~/.npm-global'
echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
npm install -g <pkg>

公式の手順(新しいタブで開く) に沿った最小構成。npm config get prefix で反映を確認する。

2. nvm / fnm / volta で入れ直す

# nvm の例
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
nvm install --lts
nvm use --lts

ホームディレクトリ以下に Node が入るため、グローバル install もすべて書き込み権限のある場所に向く。fnm / volta も方針は同じ。

3. キャッシュの所有権を戻す

sudo chown -R $(whoami) ~/.npm

過去に sudo を踏んでしまった場合の応急処置。
これを忘れると新 prefix に切り替えても EACCES が再発することがある。

4. sudo install を巻き戻す

sudo npm uninstall -g <pkg>
npm install -g <pkg>      # 新 prefix に入れ直す

以後 sudo npm を使わない方針に切り替える。
grep で履歴に残っていないかも確認しておく。

実行例

実際に上記の手順を node:20(Debian GNU/Linux 12 bookworm)環境で動かすと、一般ユーザー(nobody)による npm install -g/usr/local/lib/node_modules への mkdir を拒否されて EACCES(終了コード 243)で失敗し、prefix をユーザー領域(~/.npm-global)に張り直すことで終了コード 0 での成功まで再現できた。

$ node -v
v20.20.2
$ npm -v
10.8.2
$ npm config get prefix
/usr/local
$ ls -ld /usr/local/lib/node_modules
drwxr-xr-x 4 root root 4096 Mar 24 03:03 /usr/local/lib/node_modules
$ npm install -g is-number@7
npm error code EACCES
npm error syscall mkdir
npm error path /usr/local/lib/node_modules/is-number
npm error errno -13
npm error Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules/is-number'
npm error     at async mkdir (node:internal/fs/promises:856:10)
npm error     at async /usr/local/lib/node_modules/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js:624:20
npm error     at async Promise.allSettled (index 0)
npm error     at async [reifyPackages] (/usr/local/lib/node_modules/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js:325:11)
npm error     at async Arborist.reify (/usr/local/lib/node_modules/npm/node_modules/@npmcli/arborist/lib/arborist/reify.js:142:5)
npm error     at async Install.exec (/usr/local/lib/node_modules/npm/lib/commands/install.js:150:5)
npm error     at async Npm.exec (/usr/local/lib/node_modules/npm/lib/npm.js:207:9)
npm error     at async module.exports (/usr/local/lib/node_modules/npm/lib/cli/entry.js:74:5) {
npm error   errno: -13,
npm error   code: 'EACCES',
npm error   syscall: 'mkdir',
npm error   path: '/usr/local/lib/node_modules/is-number'
npm error }
npm error
npm error The operation was rejected by your operating system.
npm error It is likely you do not have the permissions to access this file as the current user
npm error
npm error If you believe this might be a permissions issue, please double-check the
npm error permissions of the file and its containing directories, or try running
npm error the command again as root/Administrator.
npm error A complete log of this run can be found in: /tmp/recipe-home/.npm/_logs/2026-08-02T08_45_55_340Z-debug-0.log
終了コード: 243
$ npm config set prefix ~/.npm-global
$ npm config get prefix
/tmp/recipe-home/.npm-global
$ npm install -g is-number@7
added 1 package in 528ms
終了コード: 0
$ ls ~/.npm-global/lib/node_modules
is-number
終了コード: 0

— 2026-08-02 時点の出力

この記事は役立ちましたか?