Node.jsをアップデートしたらnodeコマンドが起動直後にクラッシュするようになった問題を調査した

先日、nodenv で Node.js を 24.12.0 から 24.13.0 にアップデートしたところ、node コマンドが起動直後にクラッシュするようになった。

$ node -v
zsh: killed     node -v

プロジェクトのディレクトリに関係なく、どこで実行しても同じ症状だった。

自分では原因がわからなかったので、Claude Code に調査を依頼した。本記事では、Claude Code と一緒に原因を特定して解決するまでの流れを紹介する。

環境

調査

以下は Claude Code が実行した調査の流れをまとめたものになる。

アーキテクチャの確認

Apple Silicon 環境なので、まず x86_64 バイナリを誤ってインストールしていないか確認した。

$ file ~/.nodenv/versions/24.13.0/bin/node
Mach-O 64-bit executable arm64

正しく arm64 バイナリだったので、アーキテクチャの問題ではなかった。

終了コードの確認

$ ~/.nodenv/versions/24.13.0/bin/node -v; echo "Exit code: $?"
Exit code: 137

Exit code 137 は 128 + 9 なので、SIGKILL でプロセスが強制終了されていることがわかった。ユーザーが kill したわけではないので、OS が何らかの理由で殺している。

クラッシュレポートの確認

macOS ではプロセスがクラッシュすると ~/Library/Logs/DiagnosticReports/ にレポートが生成される。

$ ls -lt ~/Library/Logs/DiagnosticReports/ | head -5
-rw-------  5354 Jan 28 14:35 node-2026-01-28-143517.ips
...

node のクラッシュレポートが大量に生成されていた。中身を確認すると、以下の記述があった。

{
  "exception": {
    "type": "EXC_CRASH",
    "signal": "SIGKILL (Code Signature Invalid)"
  },
  "termination": {
    "namespace": "CODESIGNING",
    "indicator": "Taskgated Invalid Signature"
  }
}

原因

コード署名が無効だった。

codesign -dv で確認すると署名情報は表示されていたが、実際の検証には失敗していた。macOS のセキュリティ機構(Gatekeeper / Taskgated)がバイナリを信頼できないと判断し、起動直後に SIGKILL で強制終了していた。

nodenv でのインストール時に、ダウンロードの破損またはビルドプロセスで署名が壊れた可能性がある。

解決策(再インストール)

今回は再インストールで解消した。アドホック署名という方法もあるらしい。

nodenv uninstall 24.13.0
nodenv install 24.13.0

まとめ

macOSzsh: killed が出たときは、まずクラッシュレポートを確認するのが近道だった。Code Signature Invalid が出ていたら、署名の破損を疑うとよい。

nodenv や nvm などでインストールしたバイナリが壊れることは稀だと思うが、ネットワークの問題などでダウンロードが中途半端になった場合に起こりうる。再インストールで解決するケースが多いと思われる。

こういうログについては知らなかったので、Claude Codeがなかったら相当解決まで時間がかかっただろう。便利な時代である。

一次情報を確認しておくとお得

何か分からないことがあって社内のドキュメントを調べたり人に聞いたりして回答を得た時、回答をもらって満足するのではなく一次情報を確認しておくといい。

例えば、AWSやGooge Cloudの設定や挙動のようなものだと、そもそもドキュメントに書かれていることや人の回答が本当に正しいのか分からない。現在だと変わっているかもしれないし、勘違いなどで誤った解答をもらっているかもしれない。誤りの内容によっては大きな問題になる可能性がある。一次情報を確認しておくことで、それらに気づくことができるのでお得。

また、一次情報を一度確認しておけば、その後も自分で確認できるのもお得である。一度調べたことは大体二度、三度と調べる(僕だけかもしれない)ので、調べ方を憶えておけば確認したくなった時に人に聞かず自分で確認できるし、誰かに聞かれた時も「こうやって確認できますよ」というふうに確認の仕方を教えることもできるようになる。

自分も完全にできているわけではなく、人から聞いてフーンとなって終わることも多いし、時間がないと調べずに終わることも多いのだが、意識したいと思っているので書いた。

命名規則は簡単でもいいから最初に決めたほうがいい

AWSのアカウント名やGoogle Cloudのプロジェクト名、その中で作成するリソース名などの命名規則は簡単でもいいから最初に決めておくとよさそう。特にprefixとsuffixについてはそろえておくと後々困りにくくなるんじゃないか、とはいえ経験したことが無いとプロダクト開発の一番最初にそこまで考えることもなかなかないかも、という話。

何かを自動化しようとした時、対象のリソース名を生成することはよくある。Production、Staging、Developmentなどの環境があるとき、その環境を識別するためにこの時、命名規則がなくバラバラだとちょっとだけややこしいコードになる。

例えば、全環境でProduction/Staging/Developmentを識別するSuffixがつけられている場合、 `foobar_${env}` のように素直にリソース名を生成できる。ここで、ProductionとStagingにはSuffixがなく、DevelopmentにだけSuffixがある場合は環境によってSuffixをつけるかつけないかの条件分岐が必要となり、少しだけややこしいコードになる。

他にもある。S3バケットのようなリソースに名前をつける際、あるバケット名は `foobar_${env}` なのに他のバケット名は `${env}_hoge` だったりすると、自動化しにくい。

さらに、あるリソースではsuffxに `prod` を使っているのに別のリソースでは `production` や `prd` を使っていたりすると、これまた自動化しにくい。

プロダクト名をprefixに、環境名(prod/stg/dev/testなど)をsuffixにする、という簡単なものでもいいから決めてそれを守っておくと後々ちょっと楽になるかもしれない。

とはいえ、動くプロダクトをまずは作って売るぞ!というような一番最初にどこまで命名規則を意識できるのか、筆者には経験がないので分からない。一度経験すればその後は意識するとは思う。後、命名規則を決めてもクラウド側の文字数制限や使える文字の制限で決めた規則が使えない、ということもあると思う。可能な限り守って、どうしても遵守できない場合はちょっと規則から外れることもやむなしなのかもしれない。