React Native

【Volta】「Volta error: Node is not available.」となり、突然npmやnpxが使えなくなり焦った件

React Native
この記事は約4分で読めます。

はじめに

一昔前は、Nodeのバージョン管理ツールというとnodenvだったと思いますが、動作が軽快なので私はVoltaを使うようになりました。
設定も簡単なので特にストレスなく使用していましたが、ある日突然Voltaのエラーが出て困ったので、同じような困った方に対処する方法としてメモを残しておこうと思いました。

結論

vs codeのプロジェクト内のターミナルからnpx react-native run-iosをかけたことが原因。該当ディレクトリで

volta setup

を実行すると治った。

まず、エラー内容確認

エラーの内容そのまま載せておきます。

原因は…?

すると、次のような記事を見つけました(だいたい困ったときってgithubとかstackoverflowに助けられることが多いように感じますね…)。

Volta Node is not available when opening a bash terminal · Issue #1007 · volta-cli/volta
Currently I use iTerm with zsh and using volta from there works flawlessly, the problem start when I try to open the default macos terminal application (also wi...

ここに、長いですが、以下のような記載がありました。

Okay, thanks to the additional info, I was able to reproduce locally and figure out what’s going on:

Internally, we use an environment variable to prevent recursing infinitely (we set it when we run node and then check it if we are invoked again)
If that environment variable is set, we skip doing the Node version resolution, because the only time we set that value is when we are modifying the PATH to have node available directly.
In this case (npx react-native run-ios), our assumption is broken:
i. Running npx react-native run-ios goes through Volta, so we set the environment variable and the PATH appropriately.
ii. Internally, react-native launches a separate terminal which inherits the environment variables from the react-native process (including the recursion one we set in step i)
iii. However, since it is a new Terminal, the shell starts up and rewrites the PATH, so that isn’t inherited from the react-native process.
iv. The end result is that you wind up with an environment that is a fresh shell with no PATH modifications but at the same time has the Volta recursion environment variable already set.
v. Volta doesn’t handle that case and so it either goes into a loop or acts as though it doesn’t know how to find Node at all.

https://github.com/volta-cli/volta/issues/1007

なんとなく以下のような感じでしょうか(完全意訳です)。

vscodeから「npx react-native run-ios」を実行すると、metroが起動するタイミングで別ターミナルが起動するが、そのときに環境変数の受け渡しがうまくいかずnodeのエラーになってしまう。

ふむ。なるほど。ではどうすればいいのかな…簡単な解決法あるといいんだけど…

あったわ。

$ volta setup

これも上記のgithubの一番最後に記載してありました。これでnodeをvolta経由で再読み込みかけてくれるはず。

※Open a new terminal…(略)ってなっているので一旦ターミナルは完全に終了してくださいね!

そして、ターミナルを開き直して改めてnode -vをすると…

キタ━━━━(゚∀゚)━━━━!!

最後に

vscodeでプロジェクトを開いて、そのままvscodeのターミナルからコマンド叩くことって自然だと思うんですよね。

今回は、そんな自然な流れにもかかわらず詰まってしまったvoltaの対処法について共有でした。

でも原因がわかったのでスッキリ。次回からはreact-nativeのようなターミナルから別のターミナルに情報をと渡してビルドするような場合はvscodeではなくてターミナルで完結するようにしようと思います。