angular/components · error · Error

LuxonDateAdapter: Cannot format invalid date.

Error message

LuxonDateAdapter: Cannot format invalid date.

What it means

LuxonDateAdapter.format refuses to format an invalid LuxonDateTime, because Luxon would return the string 'Invalid DateTime' and silently corrupt the UI. The adapter throws a descriptive error instead, enforcing that only valid dates reach the display layer.

Source

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

          return fromFormat;
        }
      }

      return this.invalid();
    } else if (typeof value === 'number') {
      return LuxonDateTime.fromMillis(value, options);
    } else if (value instanceof Date) {
      return LuxonDateTime.fromJSDate(value, options);
    } else if (value instanceof LuxonDateTime) {
      return LuxonDateTime.fromMillis(value.toMillis(), options);
    }

    return null;
  }

  format(date: LuxonDateTime, displayFormat: string): string {
    if (!this.isValid(date)) {
      throw Error('LuxonDateAdapter: Cannot format invalid date.');
    }
    if (this._useUTC) {
      return date.setLocale(this.locale).setZone('utc').toFormat(displayFormat);
    } else {
      return date.setLocale(this.locale).toFormat(displayFormat);
    }
  }

  addCalendarYears(date: LuxonDateTime, years: number): LuxonDateTime {
    return date.reconfigure(this._getOptions()).plus({years});
  }

  addCalendarMonths(date: LuxonDateTime, months: number): LuxonDateTime {
    return date.reconfigure(this._getOptions()).plus({months});
  }

  addCalendarDays(date: LuxonDateTime, days: number): LuxonDateTime {
    return date.reconfigure(this._getOptions()).plus({days});

View on GitHub (pinned to 0411926e7d)

Solutions

  1. Check `adapter.isValid(date)` before formatting and render a placeholder for invalid values.
  2. If the date came from JSON persistence, rehydrate with `LuxonDateTime.fromISO`/`fromMillis`, not JSON.parse.
  3. Handle parse() returning null for unparseable input before using the result.
  4. Catch this error at the display boundary and fall back to a fallback string like '—' or 'Invalid date'.

Example fix

// before
const text = adapter.parse(userInput, 'yyyy-MM-dd');
display = adapter.format(text, 'dd/MM/yyyy'); // may throw

// after
display = text && adapter.isValid(text) ? adapter.format(text, 'dd/MM/yyyy') : '—';
Defensive patterns

Strategy: type-guard

Validate before calling

function safeFormat(adapter: DateAdapter<LuxonDateTime>, date: LuxonDateTime | null, fmt: string): string {
  return date && adapter.isValid(date) ? adapter.format(date, fmt) : '—';
}

Type guard

function isValidLuxonDate(adapter: DateAdapter<LuxonDateTime>, d: LuxonDateTime | null | undefined): d is LuxonDateTime {
  return d != null && adapter.isValid(d);
}

Try / catch

try {
  return adapter.format(date, displayFormat);
} catch (e) {
  if (String(e.message).includes('Cannot format invalid date')) return 'Invalid date';
  throw e;
}

Prevention

When it happens

Trigger: Calling `adapter.format(date, displayFormat)` with a date that came from `LuxonDateTime.invalid(...)`, from a failed `fromFormat`/`fromISO` call, or from `adapter.createDate` logic bypassed manually; also when a date stored/retrieved from storage deserialized to an invalid DateTime.

Common situations: Displaying dates parsed from malformed user input without checking isValid; reviving persisted dates with JSON.parse (produces plain objects/invalid DateTimes); passing results of failed parse() calls straight into the datepicker's display pipeline.

Related errors


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