npm ciで「Exit handler never called!」エラーが発生したときの対処法
概要
今回はnpm ci を実行したときに発生する「Exit handler never called!」エラーの対処法について紹介していきます。
CI環境やローカルで依存関係を再インストールしようとして npm ci を叩いたら、見慣れない「Exit handler never called!」というメッセージで止まってしまった、という経験はありませんか(- -;
これはnpm自体の内部エラーで、キャッシュの破損や node_modules 側の不整合が原因で発生することが多いです。
対処法はいろいろあると思いますが、少なくともチームで動いている場合は誰かしらはその手順でできているのですよね。。。
自分だけ通らない。。。そういった無いように寄り添った内容となっています(^^b
それではやっていきましょう(^^!
玄人の方はすでに実施済みの内容が書かれているだけの可能性が高いため「あーね。そりゃそうだ」程度に思っておいてください。
目次
発生するエラーの内容
実際に npm ci を実行すると、以下のようなエラーが出力されます。
コマンド
1 | npm error Exit handler never called! |
メッセージにも書かれている通り、これはnpm自体の不具合として扱われるエラーです。
ただ実際のところ、手元の環境に残っている壊れたキャッシュや中途半端な node_modules が引き金になっているケースがほとんどです。
そのため、問題を周りに報告する前にまずはローカル側の状態をリセットして再実行するのが定石です(^^b
何もやらずに質問すると無能扱いされるので注意ですよ!
対処法1:npmのキャッシュをクリアする
まず最初に試すべきは、npmのキャッシュを強制的にクリアすることです。
以下のコマンドを実行してください。
コマンド
1 | npm cache clean --force |
--force を付けないとnpm側で警告が出て実行できない(最近のnpmでは cache clean が既定で保護されているため)ので、必ず付与します。
キャッシュのクリアが終わったら、改めて npm ci を実行します。
コマンド
1 | npm ci |
これで正常に依存関係のインストールが走れば解決です。
CIサーバーの場合もキャッシュディレクトリを掃除してから再実行する(GitHub Actionsなら actions/cache のキーを変える等)だけで通ることがあります。
対処法2:node_modulesを削除して再インストール
キャッシュクリアでも解消しない場合は、プロジェクト配下の node_modules を丸ごと削除してから再実行します。
依存関係の一部だけが壊れているようなケース(ネットワーク切断時に中途半端にダウンロードされた等)では、キャッシュをクリアしても node_modules 側の壊れたファイルが残り続けるため、こちらの手順が効きます。
Linux / macOSの場合
コマンド
1 | rm -rf node_modules |
Windowsの場合
PowerShellなら以下のコマンドで削除できます。
コマンド
1 | Remove-Item -Recurse -Force node_modules |
コマンドプロンプトの場合は rmdir /s /q node_modules でもOKです。
node_modules は package-lock.json の内容に従って完全に再生成されるため、削除しても問題ありません。
もちろんGUIから削除してもOKです(^^b
注意:チーム開発の場合、package-lock.jsonは絶対に削除しないこと
ここが今回一番伝えたいポイントです。
package-lock.jsonは絶対に削除しないでください。
AIに質問してみると「気軽に消していいよ」見たいなことを言われることがありますが、チーム開発の現場では非常に危険です。
理由は以下の通りです。
npm ciはpackage-lock.jsonに記載された正確なバージョンで依存関係を再現するコマンドです。- lockファイルが無いと
npm ci自体が動かず、代わりにnpm installを使うしかなくなる npm installはpackage.jsonのバージョン範囲から最新のものを取ってくるため、知らないうちに依存関係のバージョンが変わってしまう- 結果として「ローカルでは動いていたのに本番だけ壊れる」という事故の原因になる
また意図しないバージョンのインストールによりセキュリティインシデントが発生する可能性があります。
非常に危険です。
エラーが出ているからといって、再現性の要である package-lock.json を消す方向に走らないようにしましょう。
lockファイルの更新が必要な場合は、意図的に npm install <パッケージ名> を叩いて差分を取るのが正しい流れです。
「エラー回避のために消す」というのは、依存関係管理の根幹を崩す行為になるので避けてください。
まとめ
今回の対処フローを整理すると、以下の順番になります。
- 手順1:
npm cache clean --forceでキャッシュをクリアしてnpm ciを再実行 - 手順2:それでもダメなら
node_modulesを削除してnpm ciを再実行 - 禁止事項:
package-lock.jsonは絶対に削除しない
Exit handler never called! はnpm内部のエラー表示ですが、実際はローカル側のキャッシュや node_modules を掃除するだけで直るケースがほとんどです。
焦って package-lock.json を消してしまうと、あとで依存バージョンの食い違いに悩まされることになるので、今回の手順をそのままたどってみてください(^^
以上となります。
エンジニアは一歩間違えるとすべてを終わらせられるので慎重に行きましょう!
それではお疲れ様です!