louislam/uptime-kuma · error · Error
Invalid end date
Error message
Invalid end date
What it means
Sibling of the start-date check, applied to obj.dateRange[1] (the end of the maintenance window). `new Date(obj.dateRange[1])` must produce a valid date with year <= 9999. The two checks are independent, so a payload with a good start but bad end will set start_date on the bean first and then throw here — callers should treat jsonToBean as atomic and not persist a half-filled bean.
Source
Thrown at server/model/maintenance.js:172
bean.interval_day = obj.intervalDay;
bean.timezone = obj.timezoneOption;
bean.active = obj.active;
if (obj.dateRange[0]) {
const parsedDate = new Date(obj.dateRange[0]);
if (isNaN(parsedDate.getTime()) || parsedDate.getFullYear() > 9999) {
throw new Error("Invalid start date");
}
bean.start_date = obj.dateRange[0];
} else {
bean.start_date = null;
}
if (obj.dateRange[1]) {
const parsedDate = new Date(obj.dateRange[1]);
if (isNaN(parsedDate.getTime()) || parsedDate.getFullYear() > 9999) {
throw new Error("Invalid end date");
}
bean.end_date = obj.dateRange[1];
} else {
bean.end_date = null;
}
if (bean.strategy === "cron") {
bean.duration = obj.durationMinutes * 60;
bean.cron = obj.cron;
this.validateCron(bean.cron);
}
if (bean.strategy.startsWith("recurring-")) {
bean.start_time = parseTimeFromTimeObject(obj.timeRange[0]);
bean.end_time = parseTimeFromTimeObject(obj.timeRange[1]);
bean.weekdays = JSON.stringify(obj.weekdays);
bean.days_of_month = JSON.stringify(obj.daysOfMonth);View on GitHub (pinned to 6b5ea01557)
Solutions
- Send dateRange[1] as a valid ISO 8601 string later than dateRange[0].
- Validate both endpoints client-side before POST/PUT to /api/maintenance/*.
- If only a single-point window is needed, send the same valid timestamp for both range slots.
- Reject empty/whitespace strings before they reach new Date().
Example fix
// before
if (obj.dateRange[1]) {
const parsedDate = new Date(obj.dateRange[1]);
if (isNaN(parsedDate.getTime()) || parsedDate.getFullYear() > 9999) {
throw new Error("Invalid end date");
}
bean.end_date = obj.dateRange[1];
}
// after — also enforce ordering and report the bad input
if (obj.dateRange[1]) {
const end = new Date(obj.dateRange[1]);
const start = bean.start_date ? new Date(bean.start_date) : null;
if (isNaN(end.getTime()) || end.getFullYear() > 9999) {
throw new Error(`Invalid end date: ${JSON.stringify(obj.dateRange[1])}`);
}
if (start && end < start) {
throw new Error("End date must not be earlier than start date");
}
bean.end_date = end.toISOString();
} Defensive patterns
Strategy: validation
Validate before calling
function isValidMaintenanceDate(v) {
if (!v) return true;
const d = new Date(v);
return !isNaN(d.getTime()) && d.getFullYear() <= 9999;
}
function assertValidRange(dateRange) {
if (!isValidMaintenanceDate(dateRange?.[0])) throw new Error("Invalid start date");
if (!isValidMaintenanceDate(dateRange?.[1])) throw new Error("Invalid end date");
if (dateRange?.[0] && dateRange?.[1] && new Date(dateRange[1]) < new Date(dateRange[0])) {
throw new Error("End date must not be earlier than start date");
}
} Type guard
function isValidRange(dateRange) {
const [s, e] = dateRange || [];
const ok = (v) => !v || (!isNaN(new Date(v).getTime()) && new Date(v).getFullYear() <= 9999);
return ok(s) && ok(e) && (!s || !e || new Date(e) >= new Date(s));
} Try / catch
try {
await Maintenance.jsonToBean(bean, obj);
} catch (e) {
if (/Invalid (start|end) date/.test(e.message)) {
// highlight the offending date field in the UI
}
throw e;
} Prevention
- Validate the whole dateRange client-side, including ordering, before submit.
- Use a single date-time picker component that emits ISO strings.
- Do not let raw text inputs reach the maintenance API.
When it happens
Trigger: Maintenance payload where dateRange[1] is malformed, empty-but-truthy (e.g. a whitespace string), or out of year range. Also triggered when the frontend sends an end date earlier than the start — though note this code does NOT validate ordering, only validity; ordering must be checked elsewhere.
Common situations: Frontend bug that omits or mangles the end date; API caller sending only a start date and a placeholder end; locale issues; date pickers that allow manual typing of bad values.
Related errors
- Invalid start date
- Maintenance not found
- Invalid Docker response, is it Docker really a daemon?
- domain_expiry_unsupported_monitor_type
- domain_expiry_unsupported_missing_target
AI-assisted analysis of louislam/uptime-kuma@6b5ea01557 (2026-08-12).
Data as JSON: /api/errors/995d7bdea754fd1f.
Report an issue: GitHub.