npm の EACCES: Permission Denied エラーを修正する方法
CLI ツールをインストールしようと npm install -g を実行したのに、クリーンなインストールどころか、次のようなエラーが表示される:
npm ERR! code EACCES
npm ERR! errno -13
npm ERR! syscall access
npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node_modules'
この npm の EACCES エラーは、macOS や Linux で開発者が遭遇する最も一般的な Node.js のパーミッションエラーの一つです。本記事では、その原因と適切な解決方法を解説します。
重要なポイント
- EACCES エラーは、npm が
/usr/local/lib/node_modulesのような root 所有のディレクトリへ書き込もうとして、ユーザーアカウントにアクセス権がないために発生します。 - 推奨される解決策は、nvm のようなバージョンマネージャー経由で Node.js をインストールすることです。これにより、すべてがホームディレクトリ内に配置されます。
- 代替案として、npm の prefix を変更し PATH を更新することで、ユーザー所有のグローバルディレクトリを使うように設定できます。
sudo npm install -gは避けましょう。長期的なパーミッション問題やセキュリティリスクの原因となります。- 一度きりの CLI 利用であれば、
npxを使えばグローバルインストールせずにパッケージを実行できます。
npm の Permission Denied エラーが発生する理由
npm install -g を実行すると、npm は /usr/local/lib/node_modules のようなシステムレベルのディレクトリに書き込みを行います。公式インストーラーやシステムのパッケージマネージャーで Node.js をインストールした場合、そのディレクトリは通常 root の所有になっています。一般ユーザーアカウントには書き込み権限がないため、インストールが失敗します。
これは Unix 系システムのセキュリティ機能 であり、バグではありません。解決策は保護機能を無効化することではなく、ユーザーが所有する場所を npm に使わせることです。
重要な区別: この記事では グローバルインストール のパーミッションエラーについて扱っています。ローカルプロジェクトの
node_modulesフォルダ内でパーミッションエラーが発生する場合は、原因が異なります。通常はプロジェクトディレクトリ内のファイル所有者の不一致が原因です。
npm のグローバルインストールのパーミッションを修正する: 2つの安全なアプローチ
オプション 1: バージョンマネージャーで Node.js を再インストールする(推奨)
npm は EACCES エラーを完全に回避するため、nvm のような Node バージョンマネージャーの使用を公式に推奨しています。nvm で Node をインストールすると、すべてがホームディレクトリ内に配置されます。これはデフォルトでユーザーが所有する場所であり、root 権限は一切不要です。
nvm をインストール:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/HEAD/install.sh | bash
次に Node をインストール:
nvm install --lts
これで npm install -g は sudo やパーミッション変更なしに動作します。さらに、nvm はプロジェクトごとに Node のバージョンを切り替えることができるという、他の方法にはない利点があります。
注意: 既にカスタムの npm prefix を設定している場合、nvm は内部で独自の prefix を管理します。両方のアプローチを同じ環境で併用すると競合する可能性があるため、避けてください。
オプション 2: ユーザー所有の npm グローバルディレクトリを設定する
nvm を使いたくない場合は、npm のグローバルインストール先をユーザーが所有するディレクトリにリダイレクトできます。これは npm 公式ドキュメント で説明されている代替手段です。
mkdir ~/.npm-global
npm config set prefix '~/.npm-global'
次に bin ディレクトリを PATH に追加します。bash の場合は ~/.profile または ~/.bashrc に以下を追加:
export PATH=~/.npm-global/bin:$PATH
zsh の場合は同じ行を ~/.zshrc に追加し、再読み込み:
source ~/.zshrc
sudo なしでパッケージをインストールして動作を確認:
npm install -g npm-check-updates
Discover how at OpenReplay.com.
sudo npm install -g についてはどうか?
避けてください。sudo で npm を実行すると、ファイルが root 所有としてインストールされ、後々さらなるパーミッション問題を引き起こします。また、悪意のある、あるいは侵害されたパッケージが昇格権限で実行されるため、実際のセキュリティリスクも生じます。短期的な回避策ですが、状況をかえって悪化させます。
手軽な代替案: npx を使う
CLI ツールを時々しか使わないのであれば、グローバルインストール自体が不要かもしれません。npx はパッケージをグローバルにインストールせずに実行し、ローカルパッケージを使うか、一時的に取得します:
npm create vite@latest
パーミッションは不要で、グローバルディレクトリも関与しません。
どの方法を選ぶべきか?
| 状況 | 最適なアプローチ |
|---|---|
| 複数プロジェクトを管理する開発者 | nvm |
| 単一マシン、バージョン切り替えが不要 | カスタム npm prefix |
| 一度きりの CLI ツール利用 | npx |
まとめ
npm の install -g で発生する EACCES エラーの根本原因は、ほぼ常に同じです。npm が root 所有のディレクトリへ書き込もうとしているのです。nvm を使うか、自分が所有するディレクトリを npm に指定することで、根本のミスマッチを解消すれば、このエラーは完全に解消されます。
よくある質問
可能ですが、すべきではありません。sudo を使うと root 所有としてパッケージがインストールされ、後で一般ユーザーとして npm が更新や削除を行おうとした際にさらなるパーミッション問題が発生します。また、インストールスクリプトが昇格権限で実行されるため、システムをセキュリティリスクにさらします。代わりに nvm またはカスタム prefix を使ってください。
グローバルインストールは /usr/local/lib/node_modules のようなシステムディレクトリに書き込みますが、これは多くのシステムで root 所有です。ローカルインストールは、あなたが既に所有するプロジェクトディレクトリ内の node_modules フォルダに書き込みます。そのため npm install はローカルでは問題なく動作しますが、グローバルでは適切な設定なしでは失敗します。
はい、以前の prefix にインストールされていたパッケージは、新しい prefix からは利用できなくなります。新しい場所で再インストールする必要があります。prefix を変更する前に npm list -g --depth=0 で古いグローバルパッケージをリスト化しておき、新しいディレクトリの設定と PATH の更新が完了したら再インストールしてください。
基本的には影響しません。Windows は異なるパーミッションモデルを使用しており、npm のデフォルトのグローバルインストール先は既にユーザーの AppData フォルダ内にあります。EACCES エラーは、Unix スタイルのファイル所有権が /usr/local のようなシステムディレクトリへの書き込みアクセスを制御している macOS と Linux に、ほぼ限定された問題です。
Gain control over your UX
See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay. — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.