{"record":{"id":"34e44971603243eb","repo":"louislam/uptime-kuma","slug":"invalid-domain","errorCode":null,"errorMessage":"Invalid domain","messagePattern":"Invalid domain","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/model/status_page.js","lineNumber":396,"sourceCode":"\n    /**\n     * Update list of domain names\n     * @param {string[]} domainNameList List of status page domains\n     * @returns {Promise<void>}\n     */\n    async updateDomainNameList(domainNameList) {\n        if (!Array.isArray(domainNameList)) {\n            throw new Error(\"Invalid array\");\n        }\n\n        let trx = await R.begin();\n\n        await trx.exec(\"DELETE FROM status_page_cname WHERE status_page_id = ?\", [this.id]);\n\n        try {\n            for (let domain of domainNameList) {\n                if (typeof domain !== \"string\") {\n                    throw new Error(\"Invalid domain\");\n                }\n\n                if (domain.trim() === \"\") {\n                    continue;\n                }\n\n                // If the domain name is used in another status page, delete it\n                await trx.exec(\"DELETE FROM status_page_cname WHERE domain = ?\", [domain]);\n\n                let mapping = trx.dispense(\"status_page_cname\");\n                mapping.status_page_id = this.id;\n                mapping.domain = domain;\n                await trx.store(mapping);\n            }\n            await trx.commit();\n        } catch (error) {\n            await trx.rollback();\n            throw error;","sourceCodeStart":378,"sourceCodeEnd":414,"githubUrl":"https://github.com/louislam/uptime-kuma/blob/6b5ea0155793e666666745fb8d6fef1e829543a2/server/model/status_page.js#L378-L414","documentation":"Thrown by StatusPage.updateDomainNameList when an element of the domainNameList array is not a string. Each entry is stored verbatim in status_page_cname.domain, so non-string values would break CNAME matching and DNS routing.","triggerScenarios":"Call updateDomainNameList with [123, \"x\"], [null], [{domain:\"x\"}], or [true]. The check fires inside the per-domain loop after the array guard but before the empty-trim short-circuit.","commonSituations":"Mixed-type arrays from loosely-typed API clients. Object-wrapped domains from an import format that uses {domain: \"...\"}. Numeric IDs accidentally placed in the domain field.","solutions":["Ensure every element is a string; coerce with String(x) or filter non-strings out beforehand.","If your source data uses objects, map them: list.map(o => o.domain).","Validate with list.every(d => typeof d === \"string\") before calling."],"exampleFix":"// before\nawait statusPage.updateDomainNameList([ { domain: \"status.example.com\" } ]);\n// after\nawait statusPage.updateDomainNameList([ \"status.example.com\" ]);","handlingStrategy":"type-guard","validationCode":"function normalizeDomains(list) {\n  return list.map(d => typeof d === \"object\" && d ? d.domain : d).filter(d => typeof d === \"string\");\n}","typeGuard":"function isStringArray(list) {\n  return Array.isArray(list) && list.every(d => typeof d === \"string\");\n}","tryCatchPattern":"try {\n  await statusPage.updateDomainNameList(list);\n} catch (e) {\n  if (/Invalid domain/.test(e.message)) return badRequest(\"every domain must be a string\");\n  throw e;\n}","preventionTips":["Validate with list.every(d => typeof d === \"string\") before the call.","Reject object-wrapped domain payloads at the API schema layer."],"tags":["status-page","domain","validation","type-check","uptime-kuma"],"backgroundTag":null,"analyzedSha":"6b5ea0155793e666666745fb8d6fef1e829543a2","analyzedAt":"2026-08-12T23:42:12.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}