louislam/uptime-kuma · warning · TranslatableError
domain_expiry_unsupported_monitor_type
Error message
domain_expiry_unsupported_monitor_type
What it means
DomainExpiry.checkSupport(monitor) throws this TranslatableError when monitor.type is not a key in TYPES_WITH_DOMAIN_EXPIRY_SUPPORT_VIA_FIELD (src/util.ts:778). Supported types are: http, keyword, json-query, real-browser, websocket-upgrade (via 'url'), port, ping, dns, smtp, snmp (via 'hostname'), and grpc-keyword (via 'grpcUrl'). Because it extends TranslatableError, the frontend treats the message as a translation key (msgi18n=true) rather than a literal string.
Source
Thrown at server/model/domain_expiry.js:213
parseName() {
return parseTld(this.domain);
}
/**
* @returns {(null|object)} parsed domain tld
*/
get tld() {
return this.parseName().publicSuffix;
}
/**
* @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,
});
}
View on GitHub (pinned to 6b5ea01557)
Solutions
- Switch the monitor to a supported type if you genuinely need domain-expiry tracking (http/keyword/json-query/port/ping/dns/smtp/snmp/grpc-keyword/real-browser/websocket-upgrade).
- If you are developing a new monitor type that has a hostname, add it to TYPES_WITH_DOMAIN_EXPIRY_SUPPORT_VIA_FIELD in src/util.ts with the correct field name and recompile.
- In the UI, the domain-expiry option is hidden for unsupported types — if you are seeing this from the API, reproduce via the UI to confirm support status.
- Catch TranslatableError at the call site and show the i18n key to the user instead of crashing.
Example fix
// before
if (!(monitor.type in TYPES_WITH_DOMAIN_EXPIRY_SUPPORT_VIA_FIELD)) {
throw new TranslatableError("domain_expiry_unsupported_monitor_type");
}
// after — when adding a new type, extend the map first
// src/util.ts
// exports.TYPES_WITH_DOMAIN_EXPIRY_SUPPORT_VIA_FIELD["my-type"] = "hostname"; Defensive patterns
Strategy: type-guard
Validate before calling
const { TYPES_WITH_DOMAIN_EXPIRY_SUPPORT_VIA_FIELD } = require("../src/util");
function assertMonitorSupportsDomainExpiry(monitor) {
if (!(monitor.type in TYPES_WITH_DOMAIN_EXPIRY_SUPPORT_VIA_FIELD)) {
throw new Error(`Monitor type '${monitor.type}' does not support domain-expiry tracking`);
}
} Type guard
function monitorSupportsDomainExpiry(monitor) {
return monitor?.type in TYPES_WITH_DOMAIN_EXPIRY_SUPPORT_VIA_FIELD;
} Try / catch
try {
await DomainExpiry.checkSupport(monitor);
} catch (e) {
if (e.msgi18n && e.message === "domain_expiry_unsupported_monitor_type") {
// hide/disable the domain-expiry option in the UI; not an error condition
}
} Prevention
- When adding a new monitor type, update TYPES_WITH_DOMAIN_EXPIRY_SUPPORT_VIA_FIELD in the same PR.
- Gate the UI option on the same map so users never see an unsupported combination.
- Treat TranslatableError as an expected control-flow signal, not a crash.
When it happens
Trigger: Calling checkSupport with a monitor whose type is one of the unsupported kinds — push, docker, gamedig, mongodb, mysql, mqtt, radius, kahoot, selenium, ntfy, icmp-ping, dns-ping, steam-db, or any future type not in the map. The EditMonitor.vue gates the UI on the same map, so reaching this error usually means a direct API call or a type that was added without updating the map.
Common situations: Adding a new monitor type to the codebase but forgetting to extend TYPES_WITH_DOMAIN_EXPIRY_SUPPORT_VIA_FIELD; a custom plugin monitor type; calling the domain-expiry API endpoint with an arbitrary monitor id whose type is unsupported.
Related errors
- domain_expiry_unsupported_missing_target
- domain_expiry_unsupported_is_icann
- domain_expiry_unsupported_unsupported_tld_no_rdap_endpoint
- Service Name is required.
- Invalid service name. Please use the internal Service Name (
AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12).
Data as JSON: /api/errors/a25e91f39124314d.
Report an issue: GitHub.