angular/components · error · Error
Invalid date "${date}" for month with index "${month}".
Error message
Invalid date "${date}" for month with index "${month}". What it means
After constructing the Moment, createDate verifies it is valid; if the requested day does not exist in that month (e.g. February 30), the result is invalid and the adapter throws this error in ngDevMode. Unlike the earlier component checks, this catches bounds that depend on the specific month/year, such as leap-year day counts.
Source
Thrown at src/material-moment-adapter/adapter/moment-date-adapter.ts:167
createDate(year: number, month: number, date: number): Moment {
// Moment.js will create an invalid date if any of the components are out of bounds, but we
// explicitly check each case so we can throw more descriptive errors.
if (typeof ngDevMode === 'undefined' || ngDevMode) {
if (month < 0 || month > 11) {
throw Error(`Invalid month index "${month}". Month index has to be between 0 and 11.`);
}
if (date < 1) {
throw Error(`Invalid date "${date}". Date has to be greater than 0.`);
}
}
const result = this._createMoment({year, month, date}).locale(this.locale);
// If the result isn't valid, the date must have been out of bounds for this month.
if (!result.isValid() && (typeof ngDevMode === 'undefined' || ngDevMode)) {
throw Error(`Invalid date "${date}" for month with index "${month}".`);
}
return result;
}
today(): Moment {
return this._createMoment().locale(this.locale);
}
parse(value: unknown, parseFormat: string | string[]): Moment | null {
if (value && typeof value == 'string') {
return this._createMoment(value, parseFormat, this.locale);
}
return value ? this._createMoment(value).locale(this.locale) : null;
}
format(date: Moment, displayFormat: string): string {
date = this.clone(date);View on GitHub (pinned to 0411926e7d)
Solutions
- Clamp the day to the month length before constructing: Math.min(date, adapter.getNumDaysInMonth(year, month)).
- Use adapter.addCalendarDays on the first of the month instead of composing components directly.
- Fix leap-year assumptions — derive month length from the adapter, not hardcoded tables.
- Validate source data that produced the oversized day value.
Example fix
// before const d = adapter.createDate(2023, 1, 29); // Feb 29, 2023 (not a leap year) // after const maxDay = adapter.getNumDaysInMonth(2023, 1); // 28 const d = adapter.createDate(2023, 1, Math.min(29, maxDay));
Defensive patterns
Strategy: validation
Validate before calling
function canCreateDate(y: number, m: number, d: number, adapter: MomentDateAdapter): boolean {
return d >= 1 && d <= adapter.getNumDaysInMonth(y, m);
}
const d = Math.min(requestedDay, adapter.getNumDaysInMonth(y, m)); Try / catch
try {
return adapter.createDate(y, m, d);
} catch (e) {
if (e instanceof Error && e.message.includes('for month with index')) {
return adapter.createDate(y, m, adapter.getNumDaysInMonth(y, m)); // clamp to month end
}
throw e;
} Prevention
- Clamp day to adapter.getNumDaysInMonth before composing dates
- Never hardcode 31 as month length; derive from the adapter
- Test February and leap years explicitly
- Combine day/month/year from the same source date, not mixed sources
When it happens
Trigger: Calling createDate(year, month, date) where date exceeds the month's length: Feb 29 on a non-leap year, Feb 30/31, April 31, or day 31 in any 30-day month.
Common situations: Hardcoded end-of-month = 31 without month-length logic, data from systems that allow day 31 generically, leap-year bugs in custom calendar code, combining a day from one date with a month/year from another.
Related errors
- Invalid month index "${month}". Month index has to be betwee
- Invalid date "${date}". Date has to be greater than 0.
- Invalid hours "${hours}". Hours value must be between 0 and
- Invalid minutes "${minutes}". Minutes value must be between
- Invalid seconds "${seconds}". Seconds value must be between
AI-assisted analysis of angular/components@0411926e7d (2026-08-31).
Data as JSON: /api/errors/21bbffd1856c9ad4.
Report an issue: GitHub.