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 building the Date via _createDateWithOverflow, createDate checks whether the resulting .getMonth() still equals the requested month. If not, the day overflowed past the end of the month (e.g. Feb 30 rolls to March 2) and the adapter throws in dev mode to surface invalid date components.

Source

Thrown at src/material/core/datetime/native-date-adapter.ts:144

  }

  createDate(year: number, month: number, date: number): Date {
    if (typeof ngDevMode === 'undefined' || ngDevMode) {
      // Check for invalid month and date (except upper bound on date which we have to check after
      // creating the Date).
      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.`);
      }
    }

    let result = this._createDateWithOverflow(year, month, date);
    // Check that the date wasn't above the upper bound for the month, causing the month to overflow
    if (result.getMonth() != month && (typeof ngDevMode === 'undefined' || ngDevMode)) {
      throw Error(`Invalid date "${date}" for month with index "${month}".`);
    }

    return result;
  }

  today(): Date {
    return new Date();
  }

  parse(value: any, parseFormat?: any): Date | null {
    // We have no way using the native JS Date to set the parse format or locale, so we ignore these
    // parameters.
    if (typeof value == 'number') {
      return new Date(value);
    }
    return value ? new Date(Date.parse(value)) : null;
  }

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Clamp day to adapter.getNumDaysInMonth(year, month) before creating.
  2. Validate user-supplied year/month/day triplets against the calendar.
  3. Handle Feb 29 explicitly for non-leap years in form logic.

Example fix

// before
const d = adapter.createDate(2026, 1, 29); // Feb 29, 2026 not a leap year
// after
const maxDay = adapter.getNumDaysInMonth(2026, 1); // 28
const d = adapter.createDate(2026, 1, Math.min(29, maxDay));
Defensive patterns

Strategy: validation

Validate before calling

const maxDay = adapter.getNumDaysInMonth(year, month);
if (date > maxDay) {
  throw new RangeError(`${year}-${month}-${date} overflows month (max ${maxDay})`);
}
const d = adapter.createDate(year, month, date);

Type guard

function dayFitsInMonth(y: number, m: number, d: number): boolean {
  return Number.isInteger(d) && d >= 1 && d <= 31 && d <= new Date(y, m + 1, 0).getDate();
}

Try / catch

try {
  d = adapter.createDate(year, month, date);
} catch (e) {
  if (e instanceof Error && e.message.includes('for month with index')) {
    const max = adapter.getNumDaysInMonth(year, month);
    d = adapter.createDate(year, month, Math.min(date, max));
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling createDate(year, month, day) where day exceeds the month's length — Feb 30, Apr 31, or days derived from user input/leap-year-naive logic.

Common situations: Hardcoded end-of-month day 31 for all months; leap-year bugs (Feb 29 in non-leap years); constructing dates from separate year/month/day form fields without validating against daysInMonth.

Related errors


AI-assisted analysis of angular/components@0411926e7d (2026-08-31). Data as JSON: /api/errors/486555e5d4e2f26e. Report an issue: GitHub.