brew upgrade を実行後、node が使えなくなったので調べました。
症状
node -v を実行すると command not found でした。
% node -v
zsh: command not found: node
% which node
node not found
インストール状況を確認します。
% brew list | grep node
node@22
node@22 はインストール済みなのにパスが通っていない状態でした。
解決
まず通常の brew link を試みます。
% brew link node@22
Linking /opt/homebrew/Cellar/node@22/22.22.2...
Error: Could not symlink lib/node_modules/npm/node_modules/@sigstore/bundle/LICENSE
Target /opt/homebrew/lib/node_modules/npm/node_modules/@sigstore/bundle/LICENSE
already exists. You may want to remove it:
rm '/opt/homebrew/lib/node_modules/npm/node_modules/@sigstore/bundle/LICENSE'
To force the link and overwrite all conflicting files:
brew link --overwrite node@22
To list all files that would be deleted:
brew link --overwrite node@22 --dry-run
残留ファイルとの競合でエラーになりました。--overwrite で強制上書きします。
% brew link --overwrite node@22
動作確認します。
% node -v
v22.22.2
% npm -v
10.9.7
正常動作になりました。
brew upgrade 後に他のコマンドも動かなくなった場合は同様に brew link --overwrite を試してみるといいでしょう。
原因:keg-only とは
node@22 は Homebrew の keg-only パッケージです。
keg-only は、複数バージョンの共存やシステムツールとの競合を避けるために、/opt/homebrew/bin などへの自動リンクをしない仕組みです。node@22 のようにバージョンを指定してインストールしたパッケージは keg-only になります。
通常は brew link で手動リンクを張るのですが、brew upgrade のタイミングでこのリンクが外れていました。加えて旧バージョンのファイルが /opt/homebrew/lib/ に残留しており、次回リンク時に競合する状態になっていました。
punycode の警告
対応後、別作業で以下の警告が表示されました。
(node:78603) [DEP0040] DeprecationWarning: The `punycode` module is deprecated.
Please use a userland alternative instead.
Node.js v22 で組み込みの punycode モジュールが非推奨になった影響のようです。古い依存パッケージが内部で使用しているためで、自分の場合は axios、tough-cookie、jsdom 辺りが該当しました。それぞれ更新して様子を見ようと思います。
