Unitech/pm2 · error · Error
Interpreter ${app.exec_interpreter} is NOT AVAILABLE in PATH
Error message
Interpreter ${app.exec_interpreter} is NOT AVAILABLE in PATH. (type 'which ${app.exec_interpreter}' to double check.) What it means
Before launching an app, PM2 verifies the configured exec_interpreter is resolvable via which(). If not found it throws to prevent a silent spawn failure — except for the special 'node' case, which falls back to the bundled node interpreter. Any other missing interpreter aborts.
Source
Thrown at lib/Common.js:464
if (app.exec_interpreter.indexOf('python') > -1)
app.env.PYTHONUNBUFFERED = '1'
if (app.exec_interpreter == 'lsc') {
app.exec_interpreter = path.resolve(__dirname, '../node_modules/.bin/lsc');
}
if (app.exec_interpreter == 'coffee') {
app.exec_interpreter = path.resolve(__dirname, '../node_modules/.bin/coffee');
}
if (app.exec_interpreter != 'none' && which(app.exec_interpreter) == null) {
// If node is not present
if (app.exec_interpreter == 'node') {
Common.warn(`Using builtin node.js version on version ${process.version}`)
app.exec_interpreter = cst.BUILTIN_NODE_PATH
}
else
throw new Error(`Interpreter ${app.exec_interpreter} is NOT AVAILABLE in PATH. (type 'which ${app.exec_interpreter}' to double check.)`)
}
return app;
};
Common.deepCopy = Common.serialize = Common.clone = function(obj) {
if (obj === null || obj === undefined) return {};
return fclone(obj);
};
Common.errMod = function(msg) {
if (process.env.PM2_SILENT || process.env.PM2_PROGRAMMATIC === 'true') return false;
if (msg instanceof Error)
return console.error(msg.message);
return console.error(`${cst.PREFIX_MSG_MOD_ERR}${msg}`);
}
Common.err = function(msg) {View on GitHub (pinned to 31adee8048)
Solutions
- Install the interpreter and ensure it is on PATH for the PM2 daemon, then restart the daemon (pm2 kill && pm2 resurrect).
- Reference the interpreter by absolute path.
- Set interpreter:'none' if the script is directly executable.
- For node-based apps use interpreter:'node' to hit the bundled-node fallback.
Example fix
// before
{ script: 'main.py', interpreter: 'python3' }
// after
{ script: 'main.py', interpreter: '/usr/bin/python3' } Defensive patterns
Strategy: validation
Validate before calling
const which = require('which');
function resolveInterpreter(interp) {
if (!interp || interp === 'none') return interp;
if (which(interp, { nothrow: true }) == null && interp !== 'node') {
throw new Error(`Interpreter '${interp}' not found on PATH; install it or use an absolute path`);
}
return interp;
}
app.exec_interpreter = resolveInterpreter(app.exec_interpreter); Type guard
const interpreterAvailable = (i) => !i || i === 'none' || i === 'node' || which(i, { nothrow: true }) != null; Prevention
- Restart the PM2 daemon (pm2 kill && pm2 resurrect) after installing runtimes or changing PATH.
- Reference interpreters by absolute path in production configs.
- Verify `which <interpreter>` succeeds in the daemon's environment, not just your shell.
When it happens
Trigger: Setting interpreter to a runtime that isn't installed or isn't on the PM2 daemon's PATH (python3, php, ruby, deno, ts-node), or misspelling the interpreter name.
Common situations: Container missing the runtime; local dev where the interpreter is installed via nvm/asdf but PATH isn't propagated to the (already-running) PM2 daemon; typo in interpreter.
AI-assisted analysis of Unitech/pm2@31adee8048 (2026-08-13).
Data as JSON: /api/errors/1e6584d1a2b8cf73.
Report an issue: GitHub.