{"record":{"id":"f4305a85443b9a50","repo":"louislam/uptime-kuma","slug":"grafanaoncallurl-cannot-be-empty","errorCode":null,"errorMessage":"GrafanaOncallURL cannot be empty","messagePattern":"GrafanaOncallURL cannot be empty","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"server/notification-providers/grafana-oncall.js","lineNumber":15,"sourceCode":"const NotificationProvider = require(\"./notification-provider\");\nconst axios = require(\"axios\");\nconst { DOWN, UP } = require(\"../../src/util\");\n\nclass GrafanaOncall extends NotificationProvider {\n    name = \"GrafanaOncall\";\n\n    /**\n     * @inheritdoc\n     */\n    async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {\n        const okMsg = \"Sent Successfully.\";\n\n        if (!notification.GrafanaOncallURL) {\n            throw new Error(\"GrafanaOncallURL cannot be empty\");\n        }\n\n        try {\n            let config = this.getAxiosConfigWithProxy({});\n            if (heartbeatJSON === null) {\n                let grafanaupdata = {\n                    title: \"General notification\",\n                    message: msg,\n                    state: \"alerting\",\n                };\n                await axios.post(notification.GrafanaOncallURL, grafanaupdata, config);\n                return okMsg;\n            } else if (heartbeatJSON[\"status\"] === DOWN) {\n                let grafanadowndata = {\n                    title: monitorJSON[\"name\"] + \" is down\",\n                    message: heartbeatJSON[\"msg\"],\n                    state: \"alerting\",\n                };","sourceCodeStart":1,"sourceCodeEnd":33,"githubUrl":"https://github.com/louislam/uptime-kuma/blob/6b5ea0155793e666666745fb8d6fef1e829543a2/server/notification-providers/grafana-oncall.js#L1-L33","documentation":"A preflight validation guard in the Grafana Oncall provider: before any network call, it requires notification.GrafanaOncallURL to be truthy. If the field is empty/undefined/null, it throws immediately. This prevents sending a request to an undefined host and is a pure configuration check — no HTTP traffic occurs when it fires.","triggerScenarios":"A Grafana Oncall notification was saved without setting GrafanaOncallURL, or the field was cleared/migrated to empty. Triggered on any send (test, up, down, general notification) for that integration.","commonSituations":"User created the notification entry but never pasted the integration URL; URL stored under a different field name due to a form/schema change; copying a notification config that omitted the URL.","solutions":["Edit the Grafana Oncall notification integration and paste the Integration URL copied from Grafana Oncall (Alerting -> Integrations -> Generic).","Ensure the saved field name matches what the provider reads: notification.GrafanaOncallURL (case-sensitive).","Save and re-run the test notification to confirm the guard no longer fires."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (!notification.GrafanaOncallURL || typeof notification.GrafanaOncallURL !== \"string\" || !/^https?:\\/\\//.test(notification.GrafanaOncallURL)) {\n    throw new Error(\"GrafanaOncallURL must be a non-empty http(s) URL\");\n}","typeGuard":"/** @param {unknown} n */\nfunction hasGrafanaOncallURL(n) {\n    return typeof n === \"object\" && n !== null &&\n        typeof n.GrafanaOncallURL === \"string\" &&\n        n.GrafanaOncallURL.length > 0 &&\n        /^https?:\\/\\//.test(n.GrafanaOncallURL);\n}","tryCatchPattern":null,"preventionTips":["Validate required provider URLs at notification-save time so the user learns immediately, not on the first alert.","Mark the URL field required and of type url in the form schema.","Run a test send right after creating the integration."],"tags":["config","validation","grafana-oncall","missing-url"],"backgroundTag":null,"analyzedSha":"6b5ea0155793e666666745fb8d6fef1e829543a2","analyzedAt":"2026-08-12T23:42:12.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}