louislam/uptime-kuma · warning · TranslatableError
domain_expiry_unsupported_is_icann
Error message
domain_expiry_unsupported_is_icann
What it means
After confirming a non-empty target string, checkSupport runs tldts.parse on it and checks tld.isIcann. If the suffix is not on the ICANN list (private TLDs like .local, .test, .internal, .home, or suffixes from a private network), this TranslatableError is thrown with domain/publicSuffix in meta for the frontend to interpolate.
Source
Thrown at server/model/domain_expiry.js:225
* @param {Monitor} monitor Monitor object
* @throws {TranslatableError} Throws an error if the monitor type is unsupported or missing target.
* @returns {Promise<{ domain: string, tld: string }>} Domain expiry support info
*/
static async checkSupport(monitor) {
if (!(monitor.type in TYPES_WITH_DOMAIN_EXPIRY_SUPPORT_VIA_FIELD)) {
throw new TranslatableError("domain_expiry_unsupported_monitor_type");
}
const targetField = TYPES_WITH_DOMAIN_EXPIRY_SUPPORT_VIA_FIELD[monitor.type];
const target = monitor[targetField];
if (typeof target !== "string" || target.length === 0) {
throw new TranslatableError("domain_expiry_unsupported_missing_target");
}
const tld = parseTld(target);
// It must be checked first, filter out non-ICANN domains.
if (!tld.isIcann) {
throw new TranslatableError("domain_expiry_unsupported_is_icann", {
// If domain is null, use hostname as fallback for better error message.
domain: tld.domain ?? tld.hostname ?? "EMPTY DOMAIN",
publicSuffix: tld.publicSuffix,
});
}
const publicSuffix = tld.publicSuffix;
const rootTld = publicSuffix.split(".").pop();
const rdap = await getRdapServer(publicSuffix);
if (!rdap) {
throw new TranslatableError("domain_expiry_unsupported_unsupported_tld_no_rdap_endpoint", {
publicSuffix,
});
}
return {
domain: tld.domain,
tld: rootTld,View on GitHub (pinned to 6b5ea01557)
Solutions
- Use a real ICANN-registered domain for the monitor if you want expiry tracking (e.g. point the monitor at the public name even if it resolves internally).
- If you can only monitor an internal name, accept that domain-expiry is not applicable — disable the domain-expiry option for that monitor.
- Confirm the URL is parsed as you expect with `require('tldts').parse('http://myapp.local')` and inspect .isIcann and .publicSuffix.
- Do not try to fake an ICANN suffix; the underlying data simply has no expiry date.
Example fix
// before // monitor.url = "http://grafana.local" await DomainExpiry.checkSupport(monitor); // throws domain_expiry_unsupported_is_icann // after — monitor a real registered domain instead // monitor.url = "http://grafana.example.com"
Defensive patterns
Strategy: validation
Validate before calling
const { parse: parseTld } = require("tldts");
function isIcannDomain(target) {
const tld = parseTld(target);
return tld.isIcann === true;
} Type guard
function hasIcannSuffix(target) {
return parseTld(target).isIcann === true;
} Try / catch
try {
await DomainExpiry.checkSupport(monitor);
} catch (e) {
if (e.msgi18n && e.message === "domain_expiry_unsupported_is_icann") {
// domain is internal/private — disable the expiry option
}
} Prevention
- Reserve domain-expiry tracking for real ICANN domains; internal names have no expiry.
- If you monitor a private name, do not enable the domain-expiry feature for that monitor.
- Test the URL with tldts in a scratch script before enabling the feature.
When it happens
Trigger: An http monitor pointed at an internal name like http://myapp.local, http://grafana.internal, http://service.test, or an IP address where tldts cannot find an ICANN suffix. Any hostname whose public suffix is not in the Public Suffix List as ICANN-managed.
Common situations: Internal/home-lab monitoring of LAN services; monitoring by raw IP; private TLDs used for service discovery; test environments using .test or .example.
Related errors
- domain_expiry_unsupported_unsupported_tld_no_rdap_endpoint
- domain_expiry_unsupported_monitor_type
- domain_expiry_unsupported_missing_target
- No Resolver Servers specified. Please specify at least one r
- passwordTooWeak
AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12).
Data as JSON: /api/errors/5180d5ce92b8f255.
Report an issue: GitHub.