npm installのERESOLVEを直す前に、peer dependencyの衝突元を特定する

npmのERESOLVEログからpeer依存の要求元と範囲を特定し、互換性の調整と解決器条件の違いを分けて検証します。

AIものさし編集部

npm installがERESOLVEで止まったら、最初に「どのpackageが、どのpeer バージョンを要求し、実際には何が選ばれたか」を読みます。--forceや--legacy-peer-depsを足して終了コードだけを変える前に、互換性の衝突なのか、npmの解決条件や版の差なのかを分けます。

この記事はnpmのpeer dependency解決を対象にします。npm ciのmanifestとlockfile不一致、registry認証、通信障害とは別です。以下のpackage名とバージョンは架空例で、実packageの互換性を示しません。依存のinstallや動作試験も行っていません。

エラーの要求元とバージョン範囲を表にする

ログのFound、Could not resolve dependency、peerなどに相当する箇所を読み、要求元packageと対象hostを抜き出します。表示形式はnpm版で異なるため、文字列の位置だけを固定した読み方にしません。

表は横にスクロールできます

架空の構成要素バージョン・要求確認する意味
root apphost-lib 3.2.0を使用appが選んだhost
plugin-a 1.0.0peer host-lib ^2.0.0pluginが宣言した対応範囲
plugin-b 2.0.0peer host-lib ^3.0.0別pluginの対応範囲

この架空例では、host-lib 3.2.0はplugin-aの^2.0.0を満たしません。単にrootのhostを2系へ下げればplugin-bとの関係が変わります。衝突行だけを消すのではなく、同時に使うpluginとhostの組合せを一覧にします。

peerDependenciesは、pluginなどがhost tool/libraryとの互換性を表すための宣言です。npmのpackage.json資料(新しいタブで開く)で意味を確認し、通常のdependenciesと同じように「別の場所に二個入れば必ず解決する」と考えないようにします。

manifest・lock・実ツリーを区別する

package.jsonは宣言、package-lock.jsonは解決状態、node_modulesは実際に展開された状態です。installが途中で失敗した作業場所では、node_modulesが今回意図した完成形とは限りません。実行ディレクトリとworkspace、Node.js/npmの版、直前の変更も記録します。

読取中心の確認では、対象packageを指定したnpm lsで現在の依存関係を見て、npm explainでなぜ取り込まれたかをたどる方法があります。まだinstallされていないpackageは、これらの実ツリー表示だけでは判断できません。エラーログ、manifest、lock側の情報と合わせます。

表は横にスクロールできます

確認資料分かること分からないこと
package.json宣言range・workspace・overrides実行時互換性の保証
package-lock.json記録された解決状態現在のnode_modulesが同じか
npm ls現在の依存関係・問題表示未install構成の完成形
npm explain依存として入った経路upstreamが保証する対応範囲

private registryや内部package名を含むログは、公開issueへ丸ごと貼らず、再現に必要な範囲を伏せた最小例へ切り出します。.npmrcのregistry tokenも共有しません。

互換な組合せと解決器の問題を分ける

packageの公式release noteやpeer宣言を確認し、hostに対応するplugin版へ更新する、互換なhostへ合わせる、使わなくなったpluginを外す、といった候補を比較します。すべてを最新版へ上げることが、既存appにとって最小変更とは限りません。

一方、range上は成立するはずなのに失敗する場合、npm版、workspace、overrides、optional peer、解決器の既知問題も調査対象です。ERESOLVEという名前だけで必ずpackageの宣言が間違っていると断定しません。最小再現と利用版を揃え、該当する公式issueやrelease情報を確認します。

表は横にスクロールできます

状態次の確認修正後に必要な検証
peer rangeが明確に衝突対応するhost/plugin版関連機能の動作
別環境だけ成功npm版・設定・lock生成条件同じ条件で再現するか
複雑なworkspaceでのみ失敗rootと対象workspaceの依存対象範囲とlock差分
条件上成立するが失敗最小再現・npm既知問題修正候補版での再確認

回避flagが変える意味を理解する

npm config(新しいタブで開く)によれば、legacy-peer-depsは依存ツリー構築時にpeerDependenciesを無視します。--omit=peerはdiskへ展開しない扱いで、同じ意味ではありません。peer contractを無視してinstallできても、その組合せの実行時互換性が確認されたことにはなりません。

strict-peer-depsの設定も確認します。公式資料は、これを有効にすると、通常なら警告付きで解決できる深い依存のpeer競合も失敗とする場合を説明しています。個人環境の設定だけで通る状態を、チーム共通の解決と扱わないようにします。

回避策を一時採用する場合は、対象、必要な理由、未確認の互換性、外す条件を記録します。グローバル設定で全projectへ広げず、projectの管理方針に従います。lockfileやnode_modulesを削除して最初からやり直す操作を、ログ確認の前提にはしません。

install成功の後に機能を検証する

修正候補は隔離した検証環境で適用し、manifestとlockの差分を対にして確認します。解決されたhostとplugin版が意図したものか、関連するテストや実行経路が動くかを確かめます。CIとのnpm版・設定差も確認します。

完了記録には、衝突していたpeerの要求元、採用した組合せ、変更した依存、lock差分の範囲、動作確認と未確認事項を残します。installが終了した事実だけを「依存の互換性が直った」と言い換えないことが、再発時の切り分けに役立ちます。

確認した公式資料