louislam/uptime-kuma · error · Error
No heartbeat in the time window
Error message
No heartbeat in the time window
What it means
Thrown by a push-type monitor on the overdue branch: a previous heartbeat exists but more than beatInterval*1000+bufferTime ms have passed since it, or the previous beat was already down/pending. bean.duration is computed from msSinceLastBeat.
Source
Thrown at server/model/monitor.js:760
log.debug(
"monitor",
`[${this.name}] Checking monitor at ${dayjs().format("YYYY-MM-DD HH:mm:ss.SSS")}`
);
const bufferTime = 1000; // 1s buffer to accommodate clock differences
if (previousBeat) {
const msSinceLastBeat = dayjs.utc().valueOf() - dayjs.utc(previousBeat.time).valueOf();
log.debug("monitor", `[${this.name}] msSinceLastBeat = ${msSinceLastBeat}`);
// If the previous beat was down or pending we use the regular
// beatInterval/retryInterval in the setTimeout further below
if (
previousBeat.status !== (this.isUpsideDown() ? DOWN : UP) ||
msSinceLastBeat > beatInterval * 1000 + bufferTime
) {
bean.duration = Math.round(msSinceLastBeat / 1000);
throw new Error("No heartbeat in the time window");
} else {
let timeout = beatInterval * 1000 - msSinceLastBeat;
if (timeout < 0) {
timeout = bufferTime;
} else {
timeout += bufferTime;
}
// No need to insert successful heartbeat for push type, so end here
retries = 0;
log.debug("monitor", `[${this.name}] timeout = ${timeout}`);
this.heartbeatInterval = setTimeout(safeBeat, timeout);
return;
}
} else {
bean.duration = beatInterval;
throw new Error("No heartbeat in the time window");
}
} else if (this.type === "docker") {View on GitHub (pinned to 6b5ea01557)
Solutions
- Check the pusher's logs to confirm it is still POSTing to /metrics/push/<token>
- Verify the push URL and secret in the pusher exactly match the monitor
- Ensure the source host has network egress to the Uptime Kuma instance
- Increase the monitor interval if the source legitimately pushes less often
Defensive patterns
Strategy: retry
Try / catch
// A missed push window is reported as a DOWN heartbeat; retry at the source.
// Ensure the pusher has retry/backoff so transient network failures do not skip a push.
pushWithRetry(url, payload, { retries: 3, backoffMs: 2000 }); Prevention
- Make the pusher resilient: retry with backoff and alert on pusher-side failures
- Keep the monitor interval comfortably above the pusher's real cadence
When it happens
Trigger: A push monitor's push endpoint has not been called for longer than its interval plus the buffer window.
Common situations: Source-side cron/systemd timer died; firewall/network blocks the push; push URL secret changed so pushes 404; source host offline.
Related errors
- ${bean.msg}, but keyword is ${present|not} in [${data}]
- JSON query does not pass (comparing ${response} ${this.jsonP
- Failed to load docker host config
- Flip UP to DOWN
- JSON query does not pass (comparing ${response} ${monitor.js
AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12).
Data as JSON: /api/errors/02a8cc83317f1ded.
Report an issue: GitHub.