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

NativeDateAdapter.createDate rejects a day-of-month less than 1 in dev mode. Day 0 or negative would silently roll back to the last day of the previous month, so the adapter fails fast instead.

Source

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

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

  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

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Validate day >= 1 before calling createDate.
  2. Use adapter.getLastDateOfMonth(month, year) or createDate with the correct day to get month boundaries.
  3. Sanitize parsed numeric input (check isNaN and range) before constructing dates.

Example fix

// before
const lastDayPrevMonth = adapter.createDate(2026, 4, 0);
// after
const lastDayPrevMonth = adapter.addCalendarDays(adapter.createDate(2026, 4, 1), -1);
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

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

Try / catch

try {
  d = adapter.createDate(year, month, date);
} catch (e) {
  if (e instanceof Error && e.message.includes('Date has to be greater than 0')) {
    d = adapter.addCalendarDays(adapter.createDate(year, month, 1), date - 1);
  } else { throw e; }
}

Prevention

When it happens

Trigger: Calling adapter.createDate(year, month, date) with date < 1 — e.g. passing 0 to mean 'last day of previous month' or computing day offsets without clamping.

Common situations: Loop code that starts at day 0 to compute month boundaries; deserialized/parsed day values that are 0 or NaN-ish when cast; custom date pickers feeding raw user input.

Related errors


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