louislam/uptime-kuma · error · Error

Failed to create measurement: ${this.formatTooManyRequestsEr

Error message

Failed to create measurement: ${this.formatTooManyRequestsError(hasAPIToken)}

What it means

Thrown by the Globalping monitor when createMeasurement returns HTTP 429. The message is built by formatTooManyRequestsError(hasAPIToken): without an API token you are on the anonymous credit pool, with one you are on the account pool; both are exhausted when this fires. A single 500 is retried once before this path; 429 is not retried.

Source

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

        }

        if (monitor.ipFamily === "ipv4") {
            opts.measurementOptions.ipVersion = IpVersion[4];
        } else if (monitor.ipFamily === "ipv6") {
            opts.measurementOptions.ipVersion = IpVersion[6];
        }

        log.debug("monitor", `Globalping create measurement: ${JSON.stringify(opts)}`);
        let res = await client.createMeasurement(opts);

        // Retry if the server returns a 500 error
        if (!res.ok && Globalping.isHttpStatus(500, res)) {
            res = await client.createMeasurement(opts);
        }

        if (!res.ok) {
            if (Globalping.isHttpStatus(429, res)) {
                throw new Error(`Failed to create measurement: ${this.formatTooManyRequestsError(hasAPIToken)}`);
            }
            throw new Error(`Failed to create measurement: ${this.formatApiError(res.data.error)}`);
        }

        log.debug("monitor", `Globalping fetch measurement: ${res.data.id}`);
        let measurement = await client.awaitMeasurement(res.data.id);

        if (!measurement.ok) {
            throw new Error(
                `Failed to fetch measurement (${res.data.id}): ${this.formatApiError(measurement.data.error)}`
            );
        }

        const probe = measurement.data.results[0].probe;
        const result = measurement.data.results[0].result;

        if (result.status === "failed") {
            throw new Error(this.formatResponse(probe, `Failed: ${result.rawOutput}`));

View on GitHub (pinned to 6b5ea01557)

Solutions

  1. Add an API token in the monitor/globalping settings to raise limits, or add credits at the link in the message.
  2. Reduce the number or frequency of Globalping monitors (raise interval).
  3. Sponsor or host probes per Globalping's program to raise your cap.
  4. Wait for the credit window to reset if it is time-bounded.
Defensive patterns

Strategy: retry

Validate before calling

const hasToken = typeof monitor.globalpingApiToken === "string" && monitor.globalpingApiToken.length > 0;
// credits are an external quota; validate presence of token and a reasonable interval
function conservativeInterval(monitors) { return Math.max(60, Math.ceil(3600 / Math.max(1, monitors))); }

Type guard

function hasGlobalpingToken(monitor) {
  return typeof monitor?.globalpingApiToken === "string" && monitor.globalpingApiToken.length > 0;
}

Try / catch

try {
  await gp.monitor(client, monitor, heartbeat, hasToken);
} catch (e) {
  if (/run out of credits/.test(e.message)) { heartbeat.status = DOWN; heartbeat.msg = e.message; return; }
  throw e;
}

Prevention

When it happens

Trigger: Run a Globalping (ping/http/dns/traceroute/mumble) monitor after the configured or anonymous credit quota is depleted. createMeasurement returns {ok:false} with status 429 and Globalping.isHttpStatus(429,res) is true.

Common situations: Many Globalping monitors on one instance exhausting the free anonymous tier; long-running monitors after a credit grant expired; bursts of retries against a failing target; shared IP hitting the anonymous rate limit.

Related errors


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