angular/components · 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

LuxonDateAdapter.createDate validates the month argument before constructing a Luxon DateTime. Luxon itself uses 1-indexed months, and the adapter converts from the Material 0-indexed convention internally, so a month outside 0–11 is invalid input. The adapter throws this descriptive error rather than letting Luxon produce an invalid or rolled-over date.

Source

Thrown at src/material-luxon-adapter/adapter/luxon-date-adapter.ts:147

    return this._firstDayOfWeek ?? LuxonInfo.getStartOfWeek({locale: this.locale});
  }

  getNumDaysInMonth(date: LuxonDateTime): number {
    return date.daysInMonth!;
  }

  clone(date: LuxonDateTime): LuxonDateTime {
    return LuxonDateTime.fromObject(date.toObject(), {
      ...this._getOptions(),
      zone: date.zone,
    });
  }

  createDate(year: number, month: number, date: number): LuxonDateTime {
    const options = this._getOptions();

    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.`);
    }

    // Luxon uses 1-indexed months so we need to add one to the month.
    const result = this._useUTC
      ? LuxonDateTime.utc(year, month + 1, date, options)
      : LuxonDateTime.local(year, month + 1, date, options);

    if (!this.isValid(result)) {
      throw Error(`Invalid date "${date}". Reason: "${result.invalidReason}".`);
    }

    return result;
  }

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Convert 1-indexed months to 0-indexed before calling: `createDate(y, humanMonth - 1, d)`.
  2. Clamp or validate the month: `if (month >= 0 && month <= 11) adapter.createDate(y, month, d)`.
  3. If building from user input, parse via `adapter.parse(value, format)` instead of manual index math.
  4. Check for off-by-one arithmetic where month is incremented twice.

Example fix

// before
const d = adapter.createDate(2024, 12, 15); // throws: 12 out of range

// after
const d = adapter.createDate(2024, 11, 15); // December, 0-indexed
// or from a 1-indexed source:
const d = adapter.createDate(2024, humanMonth - 1, 15);
Defensive patterns

Strategy: validation

Validate before calling

function safeCreateDate(adapter: DateAdapter<LuxonDateTime>, y: number, m: number, d: number) {
  if (!Number.isInteger(m) || m < 0 || m > 11) {
    throw new Error(`month must be 0-11, got ${m}`);
  }
  return adapter.createDate(y, m, d);
}

Type guard

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

Try / catch

try {
  return adapter.createDate(y, m, d);
} catch (e) {
  if (String(e.message).startsWith('Invalid month index')) return null;
  throw e;
}

Prevention

When it happens

Trigger: Calling `adapter.createDate(year, month, day)` with month < 0 or month > 11 — e.g. passing a 1-indexed month (1–12) straight from user input or from a legacy 1-indexed API.

Common situations: Mixing 0-indexed (Material/JS Date) and 1-indexed (Luxon, human) month conventions; computing months via arithmetic that overflows (month + 1 == 12); deserializing dates from a backend that sends 1-based months.

Related errors


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