angular/components · error · Error

Invalid month index "${month}". Month index has to be betwee

Error message

Invalid month index "${month}". Month index has to be between 0 and 11.

What it means

NativeDateAdapter.createDate validates inputs in dev mode and rejects month indexes outside 0-11 (JS Date months are zero-based). Throwing early prevents silent Date rollover where month 12 would become January of the next year.

Source

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

    return 0;
  }

  getNumDaysInMonth(date: Date): number {
    return this.getDate(
      this._createDateWithOverflow(this.getYear(date), this.getMonth(date) + 1, 0),
    );
  }

  clone(date: Date): Date {
    return new Date(date.getTime());
  }

  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();

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Convert 1-based months to zero-based: createDate(year, month - 1, date).
  2. Clamp/validate month input to 0..11 before calling createDate.
  3. When advancing months, use adapter.addCalendarMonths which handles rollover instead of manual arithmetic.

Example fix

// before
const d = adapter.createDate(2026, 12, 15); // human December
// after
const d = adapter.createDate(2026, 11, 15); // zero-based December
Defensive patterns

Strategy: validation

Validate before calling

if (!Number.isInteger(month) || month < 0 || month > 11) {
  throw new RangeError(`month must be 0-11, got ${month}`);
}
const d = adapter.createDate(year, month, date);

Type guard

function isValidMonthIndex(m: unknown): m is number {
  return typeof m === 'number' && Number.isInteger(m) && m >= 0 && m <= 11;
}

Try / catch

try {
  d = adapter.createDate(year, month, day);
} catch (e) {
  if (e instanceof Error && e.message.includes('Invalid month index')) {
    d = adapter.createDate(year, Math.min(Math.max(month, 0), 11), day);
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling adapter.createDate(year, month, date) with month < 0 or month > 11 — e.g. passing human month numbers 1-12 instead of 0-11, or out-of-range computed values.

Common situations: Developers converting UI month pickers (1-12) directly to createDate; porting code from libraries using 1-based months; arithmetic like month + 1 applied twice producing 12.

Related errors


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