louislam/uptime-kuma · error · Error
PM2 process '${processName}' is ${entry.status}.
Error message
PM2 process '${processName}' is ${entry.status}. What it means
The lookup succeeded (an entry was found by name or id) but entry.status !== 'online'. PM2 exposes statuses such as stopped, errored, stopped, launching, etc. The monitor only treats 'online' as healthy, so any other status is surfaced verbatim in the interpolated message and re-thrown to mark the heartbeat DOWN.
Source
Thrown at server/monitor-types/pm2.js:30
* @param {object} heartbeat The heartbeat object to update.
* @returns {Promise<void>}
*/
async check(monitor, heartbeat) {
const processName = (monitor.system_service_name || "").trim();
const processList = await getPM2ProcessList();
const entry = processList.find((item) => item.name === processName || item.id === processName);
if (!entry) {
throw new Error(`PM2 process '${processName}' was not found.`);
}
if (entry.status === "online") {
heartbeat.status = UP;
heartbeat.msg = `PM2 process '${processName}' is online.`;
return;
}
throw new Error(`PM2 process '${processName}' is ${entry.status}.`);
}
}
module.exports = {
PM2MonitorType,
};
View on GitHub (pinned to 6b5ea01557)
Solutions
- Inspect with `pm2 describe <name>` to see why it is not online.
- Restart with `pm2 restart <name>` and, for persistence, `pm2 save` plus `pm2 startup`.
- If status is 'errored', read `pm2 logs <name> --err` for the crash cause and fix the application.
- If 'launching' lingers, raise PM2's wait_ready/expire settings or check the app's startup.
Example fix
# before pm2 stop my-app # after pm2 restart my-app && pm2 save
Defensive patterns
Strategy: try-catch
Validate before calling
async function assertPm2Online(name) {
const list = await getPM2ProcessList();
const entry = list.find(p => p.name === name || p.id === name);
if (!entry) throw new Error(`PM2 process '${name}' was not found.`);
if (entry.status !== 'online') {
throw new Error(`PM2 process '${name}' is ${entry.status}.`);
}
} Type guard
function isPm2Online(entry) {
return !!entry && entry.status === 'online';
} Try / catch
try {
await pm2Monitor.check(monitor, heartbeat);
} catch (e) {
if (/is \w+\.$/.test(e.message)) { // 'is stopped.', 'is errored.'
heartbeat.status = DOWN;
heartbeat.msg = e.message; // keep the PM2 status for the UI
}
} Prevention
- Enable PM2 keepalive and `pm2 startup` + `pm2 save` so processes return to online after reboot.
- Set max_restarts and --no-autorestart policy deliberately; monitor the resulting state.
- Alert on 'errored' distinctly from 'stopped' to prioritise crash investigation.
When it happens
Trigger: PM2 reports the process in any non-online state: stopped (`pm2 stop`), errored (crashed and exhausted restarts), launching, or one of PM2's transient states. The entry exists in the list, so the !entry check passes and execution falls through to the throw at pm2.js:30.
Common situations: Process crashed and PM2 left it in 'errored', a manual `pm2 stop`, PM2 still launching after a host restart, or --no-autorestart leaving it stopped after a crash.
Related errors
- PM2 process '${processName}' was not found.
- PM2 process name is required.
- Invalid PM2 process name.
- ${res.status()}
AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12).
Data as JSON: /api/errors/5abc66a1fb059239.
Report an issue: GitHub.