louislam/uptime-kuma · error · Error
${res.status()}
Error message
${res.status()} What it means
After navigation and screenshot capture, the monitor reads res.status() (Playwright HTTP status of the main response). Statuses in [200,400) are UP; anything else (>=400 or an error status) is thrown as res.status() + '' so the heartbeat is marked DOWN with the code. This converts a non-success HTTP response into a monitor failure.
Source
Thrown at server/monitor-types/real-browser-monitor-type.js:292
await page.waitForTimeout(monitor.screenshot_delay);
}
let filename = jwt.sign(monitor.id, server.jwtSecret) + ".png";
await page.screenshot({
path: path.join(Database.screenshotDir, filename),
});
await context.close();
if (res.status() >= 200 && res.status() < 400) {
heartbeat.status = UP;
heartbeat.msg = res.status();
const timing = res.request().timing();
heartbeat.ping = timing.responseEnd;
} else {
throw new Error(res.status() + "");
}
}
}
module.exports = {
RealBrowserMonitorType,
testChrome,
resetChrome,
testRemoteBrowser,
};
View on GitHub (pinned to 6b5ea01557)
Solutions
- Open the URL in a browser and confirm the HTTP status (DevTools Network or curl -i).
- Fix the upstream service returning the error code.
- If the error page is intentional, point the monitor at the real resource URL.
- For 502/504 from a reverse proxy, check the backend service health.
Example fix
# before GET / -> 502 Bad Gateway # after # restart the backend behind the reverse proxy, then re-test
Defensive patterns
Strategy: validation
Validate before calling
const http = require('http');
function preflightHttp(url) {
return new Promise((resolve, reject) => {
http.get(url, res => {
if (res.statusCode >= 400) reject(new Error(`Preflight: HTTP ${res.statusCode}`));
else resolve(res.statusCode);
}).on('error', reject);
});
} Type guard
function isHttpErrorStatus(code) { return typeof code === 'number' && code >= 400; } Try / catch
try {
await realBrowserMonitor.check(monitor, heartbeat, server);
} catch (e) {
if (/^\d{3}$/.test(e.message)) {
heartbeat.status = DOWN;
heartbeat.msg = `HTTP ${e.message}`;
}
} Prevention
- Point the real-browser monitor at a known-good URL.
- Use a plain HTTP monitor alongside to separate HTTP errors from page errors.
- Alert with the HTTP code so responders can route 5xx vs 4xx.
When it happens
Trigger: The page responded with an HTTP error: 404, 500, 502, 503, etc. The response object exists (navigation completed) but the status code is >= 400, so the else branch at real-browser-monitor-type.js:292 throws.
Common situations: Target page returning 404/500, upstream gateway 502/504, redirect to an error page, or maintenance pages served with a non-2xx code.
Related errors
- The oauth config is invalid. ${e.message}
- domain_expiry_unsupported_monitor_type
- domain_expiry_unsupported_missing_target
- Your JSON body is invalid. ${e.message}
- ${bean.msg}, but keyword is ${present|not} in [${data}]
AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12).
Data as JSON: /api/errors/af8048924bb0647a.
Report an issue: GitHub.