louislam/uptime-kuma · error · Error

Monitor ID is required

Error message

Monitor ID is required

What it means

Thrown by UptimeCalculator.getUptimeCalculator(monitorID) when `!monitorID` is truthy — i.e. monitorID is undefined, null, 0, NaN, or empty string. The calculator must key its in-memory cache (`UptimeCalculator.list[monitorID]`) and persist per-monitor statistics, so a missing ID is a hard stop, not a fallback.

Source

Thrown at server/uptime-calculator.js:74

    /**
     * For migration purposes.
     * @type {boolean}
     */
    migrationMode = false;

    statMinutelyKeepHour = 24;
    statHourlyKeepDay = 30;

    /**
     * Get the uptime calculator for a monitor
     * Initializes and returns the monitor if it does not exist
     * @param {number} monitorID the id of the monitor
     * @returns {Promise<UptimeCalculator>} UptimeCalculator
     */
    static async getUptimeCalculator(monitorID) {
        if (!monitorID) {
            throw new Error("Monitor ID is required");
        }

        if (!UptimeCalculator.list[monitorID]) {
            UptimeCalculator.list[monitorID] = new UptimeCalculator();
            await UptimeCalculator.list[monitorID].init(monitorID);
        }
        return UptimeCalculator.list[monitorID];
    }

    /**
     * Remove a monitor from the list
     * @param {number} monitorID the id of the monitor
     * @returns {Promise<void>}
     */
    static async remove(monitorID) {
        delete UptimeCalculator.list[monitorID];
    }

View on GitHub (pinned to 6b5ea01557)

Solutions

  1. Validate and parse the monitor id at the trust boundary before lookup: `const id = Number(monitorID); if (!Number.isInteger(id) || id <= 0) return;`.
  2. Ensure the monitor bean is stored (has an id) before any uptime-calculator call.
  3. In routes, return 400/404 early when the id param is non-numeric instead of reaching the calculator.
  4. Filter status page monitor lists for null ids before iterating.

Example fix

// before
const uc = await UptimeCalculator.getUptimeCalculator(monitor.id);

// after
if (!Number.isInteger(monitor.id) || monitor.id <= 0) {
  throw new Error("Monitor not persisted");
}
const uc = await UptimeCalculator.getUptimeCalculator(monitor.id);
Defensive patterns

Strategy: validation

Validate before calling

const id = Number(monitorID);
if (!Number.isInteger(id) || id <= 0) { throw new Error("Valid monitor id required"); }
await UptimeCalculator.getUptimeCalculator(id);

Type guard

const isPositiveInt = (v) => Number.isInteger(Number(v)) && Number(v) > 0;

Try / catch

try { await UptimeCalculator.getUptimeCalculator(monitorID); } catch (e) { if (e.message === "Monitor ID is required") return null; throw e; }

Prevention

When it happens

Trigger: Called from api-router.js:92/257/317 (badge/status/ping endpoints), status-page-router.js:99, monitor.js:1053/1317, or chart-socket-handler.js:16 with a monitorID that parseInt failed on, a monitor row whose id is 0/null, or a monitor object whose `this.id` is not yet assigned (unsaved bean). For example, `parseInt(request.params.id, 10)` returning NaN is guarded upstream in some routes but not all.

Common situations: Requesting `/api/badge/abc/status` where abc is non-numeric and the route did not pre-validate; calling monitor.stop() or getUptimeCalculator during a half-initialized monitor; a status page referencing a deleted monitor id stored as null; race condition where monitor.id is read before R.store assigns it.

Related errors


AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12). Data as JSON: /api/errors/7c5589abc24cd4ef. Report an issue: GitHub.