louislam/uptime-kuma · error · Error

${heartbeat.msg}, but keyword is ${keywordFound ? "present"

Error message

${heartbeat.msg}, but keyword is ${keywordFound ? "present" : "not"} in [${data}]

What it means

Thrown by handleKeywordForHTTP when keyword presence does not match the invert setting. With invertKeyword off, the keyword must be present; with invert on, it must be absent. The response is HTML/whitespace-stripped and truncated to 47 chars before being included so the message stays readable.

Source

Thrown at server/monitor-types/globalping.js:399

    /**
     * Handles keyword search for HTTP monitors.
     * @param {Monitor} monitor - The monitor object.
     * @param {Heartbeat} heartbeat - The heartbeat object.
     * @param {Result} result - The result object.
     * @param {Probe} probe - The probe object.
     * @returns {Promise<void>}
     */
    async handleKeywordForHTTP(monitor, heartbeat, result, probe) {
        let data = result.rawOutput;
        let keywordFound = data.includes(monitor.keyword);

        if (keywordFound === Boolean(monitor.invertKeyword)) {
            data = data.replace(/<[^>]*>?|[\n\r]|\s+/gm, " ").trim();
            if (data.length > 50) {
                data = data.substring(0, 47) + "...";
            }
            throw new Error(
                heartbeat.msg + ", but keyword is " + (keywordFound ? "present" : "not") + " in [" + data + "]"
            );
        }

        heartbeat.msg += ", keyword " + (keywordFound ? "is" : "not") + " found";
        heartbeat.status = UP;
    }

    /**
     * Handles JSON query for HTTP monitors.
     * @param {Monitor} monitor - The monitor object.
     * @param {Heartbeat} heartbeat - The heartbeat object.
     * @param {Result} result - The result object.
     * @param {Probe} probe - The probe object.
     * @returns {Promise<void>} A promise that resolves when the JSON query is handled.
     */
    async handleJSONQueryForHTTP(monitor, heartbeat, result, probe) {
        const { status, response } = await evaluateJsonQuery(

View on GitHub (pinned to 6b5ea01557)

Solutions

  1. Open the target URL and confirm whether the keyword actually appears in the response body
  2. Re-check the invertKeyword toggle — invert means the monitor is UP when the keyword is ABSENT
  3. Pick a stable, unique keyword that survives layout changes
  4. Remember the displayed response is stripped of tags/whitespace and truncated to ~47 chars

Example fix

// before: invert on, keyword appears -> DOWN
monitor.invertKeyword = true;
monitor.keyword = "maintenance";
// after: invert off when you want the keyword to be present
monitor.invertKeyword = false;
Defensive patterns

Strategy: validation

Validate before calling

// Confirm keyword semantics before running
if (!monitor.keyword || monitor.keyword.length === 0) {
    throw new Error("HTTP keyword monitor has no keyword set");
}
// invertKeyword: when true, monitor is UP only if keyword is ABSENT
const expectPresent = !monitor.invertKeyword;

Try / catch

// The thrown message already truncates the body; preserve it for alerting
if (keywordFound === Boolean(monitor.invertKeyword)) {
    throw new Error(heartbeat.msg + ", but keyword is " + (keywordFound ? "present" : "not") + " in [" + data + "]");
}

Prevention

When it happens

Trigger: keywordFound === Boolean(monitor.invertKeyword). If invert is false and keyword absent -> throw 'not present'; if invert is true and keyword present -> throw 'present'. This is the classic keyword-mismatch path for Globalping HTTP keyword monitors.

Common situations: Target page content changed so the keyword no longer appears, the keyword was set against transient content, invertKeyword is accidentally enabled/disabled, or the keyword matches part of HTML markup that gets stripped before the check re-runs.

Related errors


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