{"record":{"id":"cc4a938128c030bc","repo":"material-components/material-components-android","slug":"start-month-cannot-be-after-current-month","errorCode":null,"errorMessage":"start Month cannot be after current Month","messagePattern":"start Month cannot be after current Month","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"lib/java/com/google/android/material/datepicker/CalendarConstraints.java","lineNumber":74,"sourceCode":"    boolean isValid(long date);\n  }\n\n  private CalendarConstraints(\n      @NonNull Month start,\n      @NonNull Month end,\n      @NonNull DateValidator validator,\n      @Nullable Month openAt,\n      int firstDayOfWeek) {\n    Objects.requireNonNull(start, \"start cannot be null\");\n    Objects.requireNonNull(end, \"end cannot be null\");\n    Objects.requireNonNull(validator, \"validator cannot be null\");\n    this.start = start;\n    this.end = end;\n    this.openAt = openAt;\n    this.firstDayOfWeek = firstDayOfWeek;\n    this.validator = validator;\n    if (openAt != null && start.compareTo(openAt) > 0) {\n      throw new IllegalArgumentException(\"start Month cannot be after current Month\");\n    }\n    if (openAt != null && openAt.compareTo(end) > 0) {\n      throw new IllegalArgumentException(\"current Month cannot be after end Month\");\n    }\n    if (firstDayOfWeek < 0\n        || firstDayOfWeek > UtcDates.getUtcCalendar().getMaximum(Calendar.DAY_OF_WEEK)) {\n      throw new IllegalArgumentException(\"firstDayOfWeek is not valid\");\n    }\n    monthSpan = start.monthsUntil(end) + 1;\n    yearSpan = end.year - start.year + 1;\n  }\n\n  boolean isWithinBounds(long date) {\n    return start.getDay(1) <= date && date <= end.getDay(end.daysInMonth);\n  }\n\n  /**\n   * Returns the {@link DateValidator} that determines whether a date can be clicked and selected.","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/material-components/material-components-android/blob/ac7e18efeefb331850c561faf9ab8bf81d27ba68/lib/java/com/google/android/material/datepicker/CalendarConstraints.java#L56-L92","documentation":"CalendarConstraints validates its month window in the constructor: if openAt (the month the picker opens on) is set and start.compareTo(openAt) > 0 — i.e. the opening month lies before the lower bound — it throws IllegalArgumentException. The bounds must satisfy start <= openAt <= end for a coherent picker.","triggerScenarios":"Building CalendarConstraints via Builder with setStart(monthA) and setOpenAt(monthB) where monthB < monthA (e.g. start = today, openAt = a year ago); computing openAt from a saved selection that predates a newly configured start bound.","commonSituations":"Persisting a user's last-viewed month and later tightening constraints (e.g. 'no dates before today'); restoring picker state in onSaveInstanceState flows where start/end changed between sessions.","solutions":["Clamp openAt into [start, end] before building: openAt = max(start, min(openAt, end)) using Month.compareTo.","If opening month is unknown, leave openAt null (picker opens at start or today).","When deriving openAt from a saved selection, validate the selection still satisfies current constraints first."],"exampleFix":"// before\nval constraints = CalendarConstraints.Builder()\n    .setStart(startMonth)\n    .setOpenAt(savedOpenAt) // savedOpenAt < startMonth -> throws\n    .build()\n\n// after\nval openAt = if (savedOpenAt != null && savedOpenAt in startMonth..endMonth) savedOpenAt else null\nval constraints = CalendarConstraints.Builder()\n    .setStart(startMonth)\n    .setOpenAt(openAt)\n    .build()","handlingStrategy":"validation","validationCode":"fun buildConstraints(start: Month, end: Month, openAt: Month?): CalendarConstraints {\n  val clampedOpenAt = openAt?.let { maxOf(start, it, compareBy { it }) } // ensure openAt >= start\n  // simpler explicit form:\n  val safeOpenAt = when {\n    openAt == null -> null\n    openAt < start -> null // or start\n    openAt > end -> end\n    else -> openAt\n  }\n  return CalendarConstraints.Builder()\n      .setStart(start).setEnd(end).setOpenAt(safeOpenAt).build()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat (start, openAt, end) as one invariant: start <= openAt <= end.","Validate restored/saved months against current bounds before reuse.","Centralize constraint construction in one helper so clamping cannot be forgotten."],"tags":["android","material-components","datepicker","validation","calendar"],"backgroundTag":null,"analyzedSha":"ac7e18efeefb331850c561faf9ab8bf81d27ba68","analyzedAt":"2026-08-14T15:35:35.735Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}