louislam/uptime-kuma · error · Error

Timeout must be between ${PING_GLOBAL_TIMEOUT_MIN} and ${PIN

Error message

Timeout must be between ${PING_GLOBAL_TIMEOUT_MIN} and ${PING_GLOBAL_TIMEOUT_MAX} seconds (default: ${PING_GLOBAL_TIMEOUT_DEFAULT})

What it means

Thrown by Monitor.validate() for type "ping" when the global timeout (this.timeout, rounded) is less than ping_per_request_timeout, less than PING_GLOBAL_TIMEOUT_MIN=1, or greater than PING_GLOBAL_TIMEOUT_MAX=300 seconds. The first condition guarantees the overall deadline can fit at least one per-request deadline.

Source

Thrown at server/model/monitor.js:1741

                    `Per-ping timeout must be between ${PING_PER_REQUEST_TIMEOUT_MIN} and ${PING_PER_REQUEST_TIMEOUT_MAX} seconds (default: ${PING_PER_REQUEST_TIMEOUT_DEFAULT})`
                );
            }

            if (this.ping_count && (this.ping_count < PING_COUNT_MIN || this.ping_count > PING_COUNT_MAX)) {
                throw new Error(
                    `Echo requests count must be between ${PING_COUNT_MIN} and ${PING_COUNT_MAX} (default: ${PING_COUNT_DEFAULT})`
                );
            }

            if (this.timeout) {
                const pingGlobalTimeout = Math.round(Number(this.timeout));

                if (
                    pingGlobalTimeout < this.ping_per_request_timeout ||
                    pingGlobalTimeout < PING_GLOBAL_TIMEOUT_MIN ||
                    pingGlobalTimeout > PING_GLOBAL_TIMEOUT_MAX
                ) {
                    throw new Error(
                        `Timeout must be between ${PING_GLOBAL_TIMEOUT_MIN} and ${PING_GLOBAL_TIMEOUT_MAX} seconds (default: ${PING_GLOBAL_TIMEOUT_DEFAULT})`
                    );
                }

                this.timeout = pingGlobalTimeout;
            }
        }

        if (this.type === "real-browser") {
            // screenshot_delay validation
            if (this.screenshot_delay !== undefined && this.screenshot_delay !== null) {
                const delay = Number(this.screenshot_delay);
                if (isNaN(delay) || delay < 0) {
                    throw new Error("Screenshot delay must be a non-negative number");
                }

                // Must not exceed 0.8 * timeout (page.goto timeout is interval * 1000 * 0.8)
                const maxDelayFromTimeout = this.interval * 1000 * 0.8;

View on GitHub (pinned to 6b5ea01557)

Solutions

  1. Set timeout to an integer of seconds between 1 and 300 that is >= ping_per_request_timeout.
  2. If you want a tight check, lower ping_per_request_timeout proportionally rather than only lowering timeout.
  3. Omit timeout to use PING_GLOBAL_TIMEOUT_DEFAULT when you do not need a custom deadline.

Example fix

// before
{ type: "ping", timeout: 2, ping_per_request_timeout: 5 }
// after
{ type: "ping", timeout: 10, ping_per_request_timeout: 5 }
Defensive patterns

Strategy: validation

Validate before calling

function validPingGlobalTimeout(timeout, perRequest) {
  const t = Math.round(Number(timeout));
  return t >= 1 && t <= 300 && t >= Number(perRequest || 0);
}

Type guard

function isPingTimeoutCombo(timeout, perRequest) {
  const t = Math.round(Number(timeout));
  return Number.isInteger(t) && t >= 1 && t <= 300 && t >= (Number(perRequest) || 0);
}

Try / catch

try {
  await bean.validate();
} catch (e) {
  if (/Timeout must be between/.test(e.message)) return badRequest("global timeout must be 1..300s and >= per-ping timeout");
  throw e;
}

Prevention

When it happens

Trigger: Save a ping monitor with timeout=0, timeout=400, or a valid timeout (e.g. 2) that is smaller than ping_per_request_timeout (e.g. 5). Math.round(Number(this.timeout)) means fractional seconds are accepted but coerced.

Common situations: Setting a short global timeout while leaving a large per-ping timeout (logical impossibility). Inheriting a 60s default timeout then raising ping_per_request_timeout above it. Cluster-wide config templates that set timeout in milliseconds.

Understand the failure class

Related errors


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