angular/components · error

Invalid date "${date}". Date has to be greater than 0.

Error message

Invalid date "${date}". Date has to be greater than 0.

What it means

LuxonDateAdapter.createDate requires the day-of-month argument to be at least 1; day 0 or negative has no valid calendar meaning in this API. The adapter throws this error before constructing the Luxon DateTime so callers get a clear message instead of an invalid result.

Source

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

    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;
  }

  today(): LuxonDateTime {
    const options = this._getOptions();

    return this._useUTC ? LuxonDateTime.utc(options) : LuxonDateTime.local(options);

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Ensure the day argument is >= 1 before calling createDate.
  2. To get the last day of the previous month, construct via the adapter's other APIs or compute with Luxon directly, not with day=0.
  3. Validate user-supplied day input range 1–31 (and check month length via adapter.getNumDaysInMonth).
  4. Initialize day variables to a valid default (e.g. 1) rather than 0.

Example fix

// before
const d = adapter.createDate(2024, 2, 0); // throws

// after
const lastJan = adapter.createDate(2024, 0, adapter.getNumDaysInMonth(adapter.createDate(2024, 0, 1)));
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

function isValidDayOfMonth(d: unknown): d is number {
  return typeof d === 'number' && Number.isInteger(d) && d >= 1 && d <= 31;
}

Try / catch

try {
  return adapter.createDate(y, m, d);
} catch (e) {
  if (String(e.message).startsWith('Invalid date "') && String(e.message).includes('greater than 0')) return null;
  throw e;
}

Prevention

When it happens

Trigger: Calling `adapter.createDate(year, month, 0)` or a negative day — commonly when day arithmetic (e.g. 'yesterday' as day-1) underflows, or when a 0 default was passed for an unset day.

Common situations: Computing previous-month days manually instead of letting the adapter roll over; passing uninitialized variables defaulting to 0; porting code that relied on JS Date's day-0 rollover behavior.

Related errors


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