I had this issue and mostly there are answers that acknowledge the issue but I wanted to contribute with the clear answer I wasn't able to find.
The issue
This issue happened on my server (vps) because I installed node with nvm and this node version manager is loaded in the shell configuration file such as .bashrc if you use bash or inside .zshrc if you use zsh.
What happens when you load the shell configuration file (automatically at startup time of the shell) is that the $PATH variable, is enriched with the nvm path, such that also node is findable. This is important, because all the paths put inside the PATH variable is where the shell looks for commands.
Main point of the issue
Since Capistrano is a non-interactive command tool that runs via ssh, I don't think zshrc and hence nvm and hence node are loaded. Therefore the node command wouldn't be findable during capistrano deployment, even if it's installed.
My solution
In order to make node findable, I found the easiest solution to be to put the installed node version inside the original $PATH (that being the $PATH avaiable even without loading .zshrc). A good place to do that is /usr/bin/.
Step 1: find where is node currently
Therefore find where is your node installed:
which node
# /home/deploy/.nvm/versions/node/v16.15.1/bin/node
or
whereis node
# node: /home/deploy/.nvm/versions/node/v16.15.1/bin/node
Step 2: create symlink
Now create a soft link in /usr/bin
ln -s /home/deploy/.nvm/versions/node/v16.15.1/bin/node /usr/bin/
Step 3: verify symlink
Now if you run again whereis node it should print both paths.
whereis node
node: /usr/bin/node /home/deploy/.nvm/versions/node/v16.15.1/bin/node
If you run capistrano now, it should work without throwing execjs error.
How to update
if you update the installed node version throughout the lifetime of the project you need to remember to delete the symlink you created and reinstall it with the new node version installed.
Things I wouldn't do
- I would not install directly node on the server without a
node version manager.
- I would not modify the code inside
execjs because that library is working correctly
- I would not run v8 in ruby with
therubyracer, which just adds unnecessary overhead.
These are just workarounds that do not understand and acknowledge the main issue, which I explained above.
Other reasons
Of course, this issue and solution are relevant if you have installed node with nvm (it's advisable to use nvm but beyond the scope of this question), and capistrano still doesn't find node.
However, there could be other issues as mentioned by others such as that node is not at all installed, or execjs gem is not installed.