louislam/uptime-kuma · error · Error

Child monitors down: ${downChildren.join(", ")}; pending: ${

Error message

Child monitors down: ${downChildren.join(", ")}; pending: ${pendingChildren.join(", ")}

What it means

Thrown by the group monitor when at least one active child's last heartbeat is DOWN. The throw is intentional: it leverages the generic retry/notification flow to mark the group DOWN and alert. Pending children are appended to the message when present. This is not an exception to suppress — it is how a group reports failure.

Source

Thrown at server/monitor-types/group.js:73

            heartbeat.status = UP;
            heartbeat.msg = "All children up and running";
            return;
        }

        if (worstStatus === PENDING) {
            heartbeat.status = PENDING;
            heartbeat.msg = `Pending child monitors: ${pendingChildren.join(", ")}`;
            return;
        }

        let message = `Child monitors down: ${downChildren.join(", ")}`;

        if (pendingChildren.length > 0) {
            message += `; pending: ${pendingChildren.join(", ")}`;
        }

        // Throw to leverage the generic retry handling and notification flow
        throw new Error(message);
    }
}

module.exports = {
    GroupMonitorType,
};

View on GitHub (pinned to 6b5ea01557)

Solutions

  1. Investigate and resolve the listed DOWN child monitors first
  2. If a child is permanently broken, pause (deactivate) it so the group ignores it
  3. Add children to the group only after they have at least one heartbeat to avoid the pending list
  4. Do not catch-and-swallow this error — it drives the group's DOWN status and notifications
Defensive patterns

Strategy: try-catch

Validate before calling

// Inspect child statuses before relying on the group result
const children = await Monitor.getChildren(monitor.id);
if (children.length === 0) {
    // group will be PENDING, not an error
    return;
}

Try / catch

// The throw is intentional — let it propagate to drive DOWN status.
// Only catch if you need custom aggregation.
try {
    await groupMonitor.check(monitor, heartbeat, server);
} catch (e) {
    if (e.message.startsWith("Child monitors down:")) {
        // expected DOWN path; re-throw so notifications fire
        throw e;
    }
    throw e;
}

Prevention

When it happens

Trigger: In GroupMonitorType.check, the loop finds a child with lastBeat.status === DOWN (and active), so worstStatus becomes DOWN. The code then constructs 'Child monitors down: X' and throws. If some children are also PENDING they are appended after '; pending:'.

Common situations: A real downstream outage on one or more child monitors, a child stuck DOWN after a transient blip, or children that are misconfigured and perpetually DOWN.

Related errors


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