louislam/uptime-kuma · error · Error
Failed to create measurement: ${this.formatApiError(res.data
Error message
Failed to create measurement: ${this.formatApiError(res.data.error)} What it means
Thrown by the Globalping monitor when createMeasurement returns a non-ok, non-429, non-500 response. formatApiError renders the Globalping error object as "<type> <message>.\n<param>: <value>...". A single 500 is auto-retried before this throw; anything else (400 validation, 401/403 auth, 404, 5xx that persisted) lands here.
Source
Thrown at server/monitor-types/globalping.js:102
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
- Read the embedded <type> and <message>: validation errors name the offending field.
- For 401/403, refresh or re-enter the Globalping API token in settings.
- For location errors, use a known magic location (e.g. a region or 'magic+ww' style) from Globalping docs.
- For 5xx that is not 500, treat as transient and retry after a short delay; check status.globalping.io.
Defensive patterns
Strategy: try-catch
Validate before calling
function validateMeasurementInput(monitor) {
if (monitor.protocol === "TCP" && !monitor.port) throw new Error("TCP measurements require a port");
if (!monitor.hostname) throw new Error("hostname is required");
return true;
} Type guard
function isPlausibleGlobalpingTarget(monitor) {
return Boolean(monitor?.hostname) && (monitor.protocol !== "TCP" || Number.isFinite(Number(monitor?.port)));
} Try / catch
try {
await gp.monitor(client, monitor, heartbeat, hasToken);
} catch (e) {
if (/Failed to create measurement/.test(e.message) && !/run out of credits/.test(e.message)) {
heartbeat.status = DOWN; heartbeat.msg = e.message; return;
}
throw e;
} Prevention
- Validate target/protocol/port combos before sending to Globalping.
- Keep the API token current; rotate before expiry.
When it happens
Trigger: Submit a measurement with an invalid target/protocol/location/port combo (400), an expired or invalid API token (401/403), an unknown location magic string, or hit a Globalping outage returning 502/503 that the 500-retry did not cover.
Common situations: Wrong protocol for the measurement type (e.g. TCP without a port, set via monitor.protocol/port), unsupported location string, stale API token, Globalping maintenance window, breaking API change after a version bump.
Related errors
- Failed to create measurement: ${this.formatTooManyRequestsEr
- Failed to fetch measurement (${res.data.id}): ${this.formatA
- Monitor ID is required
- Service Name is required.
- Invalid service name. Please use the internal Service Name (
AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12).
Data as JSON: /api/errors/a71df4d1261cd103.
Report an issue: GitHub.