0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

npm installで ERESOLVE エラーが出た時の対処法

0
Posted at

やりたかったこと(または「症状」)

React 17で動いているNext.jsプロジェクトに、テスト環境を整えるため @testing-library/react の最新版を追加しようとした。いつも通り npm install --save-dev @testing-library/react を叩いたところ、ターミナルが真っ赤なエラーで埋め尽くされてインストールが止まった。

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: my-app@0.1.0
npm ERR! Found: react@17.0.2
npm ERR! node_modules/react
npm ERR!   react@"^17.0.2" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer react@"^18.0.0" from @testing-library/react@14.0.0
npm ERR! node_modules/@testing-library/react
npm ERR!   dev @testing-library/react@"^14.0.0" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
npm ERR! See /home/user/.npm/eresolve-report.txt for a full report.

node_modules は生成されず、package-lock.json も更新されない。これまで何百回も npm install してきたが、ここまで長いエラーは初めてで、何が原因なのか見当もつかなかった。

環境

  • OS: Ubuntu 22.04 LTS
  • Node.js: v20.11.0
  • npm: 10.2.4
  • React: 17.0.2
  • @testing-library/react: 14.0.0(インストールしようとしたバージョン)

試したこと

最初はエラーメッセージの下部に書かれていた npm ERR! See /home/user/.npm/eresolve-report.txt for a full report. の意味が分からず、単純にもう一度 npm install を実行し直した。

npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree

結果は同じで、まったく同じエラーが再び表示されただけだった。ネットワークの一時的な不具合ではなく、依存関係そのものに問題があると分かった。

次に、キャッシュが壊れているのではないかと考えて npm cache clean --force を実行してから再インストールした。

npm cache clean --force
npm install --save-dev @testing-library/react

キャッシュクリア自体は成功したが、インストールは同じ ERESOLVE unable to resolve dependency tree で止まった。キャッシュの問題ではなく、package.json に書かれたパッケージ同士のバージョン要求が矛盾していることが原因だと分かった。

原因

npm 7以降は、インストール対象パッケージが peerDependencies に指定しているバージョン条件を厳密にチェックするようになった。今回のケースでは、プロジェクトの react17.0.2 で固定されているのに対し、@testing-library/react@14peerDependenciesreact@^18.0.0 を要求していた。

npmは「ルートプロジェクトが要求するreact 17」と「新しく入れようとしたパッケージが要求するreact 18」の両方を同時に満たす組み合わせを解決できないため、依存関係ツリーの構築自体を中断してエラーを出す。npm 6以前はpeerDependenciesの不一致があっても警告だけで処理を進めていたが、npm 7からはこれがエラー扱いになった点が、過去にnpmを使っていた人が戸惑うポイントになっている。

解決方法

1. 根本原因のバージョンを揃える

npm install --save-dev @testing-library/react@13
added 1 package, and audited 842 packages in 4s
found 0 vulnerabilities

@testing-library/react@13peerDependenciesreact@^16.8.0 || ^17.0.0 || ^18.0.0 を許容しているため、プロジェクトのreact 17と矛盾せずインストールできる。エラーメッセージに出てきたパッケージのCHANGELOGやリリースノートを確認し、今使っているメジャーバージョンと噛み合うバージョンまで下げるのが最も安全な直し方になる。

2. どうしてもバージョンを揃えられない場合は --legacy-peer-deps を使う

npm install --save-dev @testing-library/react --legacy-peer-deps
npm warn ERESOLVE overriding peer dependency
npm warn Found: react@17.0.2
npm warn Could not resolve dependency:
npm warn peer react@"^18.0.0" from @testing-library/react@14.0.0
added 7 packages, and audited 849 packages in 6s

--legacy-peer-deps を付けると、npm 6以前と同じくpeerDependenciesの不一致を警告(warn)だけに留めてインストールを続行する。ビルドやテストの動作自体には影響しないことが多いが、想定外のReact APIが呼ばれた場合に実行時エラーになるリスクがあるため、根本解決の1番目を優先し、これは応急処置として使う。

3. インストール後、依存関係ツリーで確認する

npm ls react
my-app@0.1.0
├── react@17.0.2
└─┬ @testing-library/react@13.4.0
  └── react@17.0.2 deduped

npm ls reactreact がプロジェクト全体で1つのバージョンに統一されているか確認できる。複数バージョンが混在している場合は、後述の「よくある質問」にある npm ls での深掘りが必要になる。

ハマったポイント

  • エラーメッセージ内の While resolvingCould not resolve dependency の2つのブロックを読み飛ばし、どのパッケージ同士が衝突しているのか特定できずに30分ほど無駄にした。上のブロックが「今何を入れようとしているか」、下のブロックが「それを妨げている要求」を示している
  • --force--legacy-peer-deps を混同していた。--force はキャッシュ内の壊れたパッケージも含めて強制的に再取得・再構築するオプションで、--legacy-peer-deps はpeerDependenciesのチェックだけを緩めるオプション。今回は後者だけで十分だったのに、最初に --force を使って無関係なパッケージまで再インストールされてしまった
  • package-lock.json を手動で編集してバージョン番号だけ書き換えようとしたら、npm install 実行時に npm ERR! Invalid: lock file's react@18.2.0 does not satisfy react@17.0.2 という別のエラーが出た。lockファイルは直接編集せず、必ずnpmコマンド経由で更新する
  • CI環境(GitHub Actions)では npm ci を使っていたため、ローカルで --legacy-peer-deps 付きで解決したはずのインストールがCI上では同じERESOLVEエラーで失敗した。npm ci.npmrc の設定を読むので、.npmrclegacy-peer-deps=true を追記してCIとローカルの挙動を揃える必要があった

よくある質問

Q: npm install --force--legacy-peer-deps はどちらを使えばいいですか?
まずは --legacy-peer-deps を試す。peerDependenciesのチェックだけを緩めるため影響範囲が小さい。--force はキャッシュや既存パッケージまで強制的に上書きするため、意図しない副作用が起きやすい。両方試してもエラーが解消しない場合のみ --force を検討する。

Q: ERESOLVEエラーを毎回オプション付きで回避するのが面倒です。設定で固定できますか?
プロジェクト直下に .npmrc を作成し、legacy-peer-deps=true を1行書いておくと、以降は npm install だけでオプションなしでも同じ挙動になる。

# .npmrc
legacy-peer-deps=true

Q: どのパッケージ同士が競合しているのか、エラーメッセージだけでは分かりにくいです。
npm ls <パッケージ名> を実行すると、そのパッケージが依存関係ツリーのどこから複数バージョン要求されているかツリー表示で確認できる。

npm ls react

関連記事


この記事は errsolved.com にも掲載しています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?