louislam/uptime-kuma · warning · Error

The maximum number of hours is 720

Error message

The maximum number of hours is 720

What it means

Thrown by UptimeCalculator.getData(num, type) when `type === "hour" && num > 24 * 30` (720). Bounds the amount of hourly data points returned because the calculator only retains 30 days of hourly stats (`statHourlyKeepDay = 30`). Requesting more would silently return incomplete data, so the API fails fast instead.

Source

Thrown at server/uptime-calculator.js:565

            case UP:
            case MAINTENANCE:
                return UP;
            case DOWN:
            case PENDING:
                return DOWN;
        }
        throw new Error("Invalid status");
    }

    /**
     * @param {number} num the number of data points which are expected to be returned
     * @param {"day" | "hour" | "minute"} type the type of data which is expected to be returned
     * @returns {UptimeDataResult} UptimeDataResult
     * @throws {Error} The maximum number of minutes greater than 1440
     */
    getData(num, type = "day") {
        if (type === "hour" && num > 24 * 30) {
            throw new Error("The maximum number of hours is 720");
        }
        if (type === "minute" && num > 24 * 60) {
            throw new Error("The maximum number of minutes is 1440");
        }
        if (type === "day" && num > 365) {
            throw new Error("The maximum number of days is 365");
        }
        // Get the current time period key based on the type
        let key = this.getKey(this.getCurrentDate(), type);

        let total = {
            up: 0,
            down: 0,
        };

        let totalPing = 0;
        let endTimestamp;

View on GitHub (pinned to 6b5ea01557)

Solutions

  1. Cap the requested duration to the supported maximum: for hours use <= 720 (30 days).
  2. Switch to day type for longer ranges: request "30d" / "365d" instead of "720h"+.
  3. If building a badge URL, pass an explicit unit (e.g. 30d) rather than a bare number.
  4. Validate the duration string client-side against the m/h/d/w/M/y limits before calling the API.

Example fix

// before
const up = uptimeCalculator.getData(1000, "hour");

// after
const hours = Math.min(num, 720);
const up = uptimeCalculator.getData(hours, "hour");
// or for longer ranges:
const up = uptimeCalculator.getData(Math.min(days, 365), "day");
Defensive patterns

Strategy: validation

Validate before calling

if (type === "hour") num = Math.min(num, 720);

Type guard

const withinHourLimit = (n) => typeof n === "number" && n > 0 && n <= 720;

Try / catch

try { getData(n, "hour"); } catch (e) { if (/maximum number of hours/.test(e.message)) getData(720, "hour"); else throw e; }

Prevention

When it happens

Trigger: Reached directly via getData(num, "hour") with num > 720, or indirectly via getDataByDuration("Nh") where N > 720 (e.g. badge URL `/api/badge/:id/status/1000` normalizes to "1000h" because a pure number is treated as hours at api-router.js:245-247). Also via weekly/monthly/yearly expansions that land on hour type — but those use day type, so not here.

Common situations: Badge URL with a large bare number interpreted as hours; custom client requesting a year of hourly uptime; scripted load test passing arbitrary period values; confusion between minutes/hours/days units in the duration string.

Related errors


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