{"record":{"id":"0604ffa6413c3a92","repo":"louislam/uptime-kuma","slug":"screenshot-delay-must-be-less-than-maxdelayfromt","errorCode":null,"errorMessage":"Screenshot delay must be less than ${maxDelayFromTimeout}ms (0.8 × interval)","messagePattern":"Screenshot delay must be less than (.+?)ms \\(0\\.8 × interval\\)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/model/monitor.js","lineNumber":1761,"sourceCode":"                    );\n                }\n\n                this.timeout = pingGlobalTimeout;\n            }\n        }\n\n        if (this.type === \"real-browser\") {\n            // screenshot_delay validation\n            if (this.screenshot_delay !== undefined && this.screenshot_delay !== null) {\n                const delay = Number(this.screenshot_delay);\n                if (isNaN(delay) || delay < 0) {\n                    throw new Error(\"Screenshot delay must be a non-negative number\");\n                }\n\n                // Must not exceed 0.8 * timeout (page.goto timeout is interval * 1000 * 0.8)\n                const maxDelayFromTimeout = this.interval * 1000 * 0.8;\n                if (delay >= maxDelayFromTimeout) {\n                    throw new Error(`Screenshot delay must be less than ${maxDelayFromTimeout}ms (0.8 × interval)`);\n                }\n\n                // Must not exceed 0.5 * interval to prevent blocking next check\n                const maxDelayFromInterval = this.interval * 1000 * 0.5;\n                if (delay >= maxDelayFromInterval) {\n                    throw new Error(`Screenshot delay must be less than ${maxDelayFromInterval}ms (0.5 × interval)`);\n                }\n            }\n        }\n\n        if (this.type === \"mongodb\" && this.databaseQuery) {\n            // Validate that databaseQuery is valid JSON\n            try {\n                JSON.parse(this.databaseQuery);\n            } catch (error) {\n                throw new Error(`Invalid JSON in database query: ${error.message}`);\n            }\n        }","sourceCodeStart":1743,"sourceCodeEnd":1779,"githubUrl":"https://github.com/louislam/uptime-kuma/blob/6b5ea0155793e666666745fb8d6fef1e829543a2/server/model/monitor.js#L1743-L1779","documentation":"Thrown by Monitor.validate() for type \"real-browser\" when screenshot_delay >= interval*1000*0.8. The 0.8 factor mirrors the page.goto navigation timeout (0.8 * interval), so a delay at or above it would fire after the navigation has already timed out, making the screenshot useless.","triggerScenarios":"Save a real-browser monitor with a small interval and a large screenshot_delay, e.g. interval=20 (seconds) and screenshot_delay=16001 (>= 16000ms). The threshold recomputes from interval at validation time.","commonSituations":"User lowers the monitor interval after setting a delay and forgets to re-lower the delay. Default delay from a template that was tuned for a 60s interval applied to a 20s monitor. Mixing seconds (interval) and milliseconds (delay) mentally.","solutions":["Lower screenshot_delay to below 0.8 * interval * 1000 ms, e.g. for interval=20s keep delay < 16000ms.","Alternatively raise the monitor interval so the same delay fits under the 0.8 threshold.","Recompute the bound whenever you change interval."],"exampleFix":"// before\n{ type: \"real-browser\", interval: 20, screenshot_delay: 17000 }\n// after\n{ type: \"real-browser\", interval: 20, screenshot_delay: 12000 }","handlingStrategy":"validation","validationCode":"function delayFitsTimeout(delayMs, intervalSec) {\n  return Number(delayMs) < intervalSec * 1000 * 0.8;\n}","typeGuard":"function isDelayUnderTimeoutBound(delayMs, intervalSec) {\n  const n = Number(delayMs);\n  return Number.isFinite(n) && n < intervalSec * 1000 * 0.8;\n}","tryCatchPattern":"try {\n  await bean.validate();\n} catch (e) {\n  if (/0\\.8 . interval/.test(e.message)) return badRequest(\"screenshot_delay must be < 0.8 * interval ms\");\n  throw e;\n}","preventionTips":["Recompute the bound whenever interval changes.","Show a live max-delay hint derived from interval in the UI."],"tags":["monitor","real-browser","validation","timeout","uptime-kuma"],"backgroundTag":null,"analyzedSha":"6b5ea0155793e666666745fb8d6fef1e829543a2","analyzedAt":"2026-08-12T23:42:12.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}