{"record":{"id":"0c7de5f9a05ed973","repo":"material-components/material-components-android","slug":"current-month-cannot-be-after-end-month","errorCode":null,"errorMessage":"current Month cannot be after end Month","messagePattern":"current Month cannot be after end Month","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"lib/java/com/google/android/material/datepicker/CalendarConstraints.java","lineNumber":77,"sourceCode":"  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.\n   */\n  public DateValidator getDateValidator() {\n    return validator;","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/material-components/material-components-android/blob/ac7e18efeefb331850c561faf9ab8bf81d27ba68/lib/java/com/google/android/material/datepicker/CalendarConstraints.java#L59-L95","documentation":"The companion check in CalendarConstraints: when openAt is non-null and openAt.compareTo(end) > 0, the opening month is past the upper bound and the constructor throws IllegalArgumentException. Together with the start check it enforces start <= openAt <= end, preventing a picker that opens outside its own selectable range.","triggerScenarios":"Builder().setOpenAt(month) with month after setEnd(month); computing openAt from 'today' while end is capped in the past (e.g. birthdate picker with end = today - 18y and openAt defaulting to today); restoring an old selection newer than a tightened end bound.","commonSituations":"Date pickers with future dates disallowed (end = today) combined with an openAt computed from a previously selected future date; symmetric to the start violation and appears in the same state-restoration flows.","solutions":["Clamp openAt to the bounds before building the constraints.","Omit setOpenAt entirely when there is no trustworthy value; the picker picks a default month within bounds.","Re-validate restored selections against current start/end before feeding them back."],"exampleFix":"// before\nval constraints = CalendarConstraints.Builder()\n    .setEnd(endMonth)\n    .setOpenAt(Today) // Today > endMonth -> throws\n    .build()\n\n// after\nval openAt = if (todayMonth > endMonth) endMonth else todayMonth\nval constraints = CalendarConstraints.Builder()\n    .setEnd(endMonth)\n    .setOpenAt(openAt)\n    .build()","handlingStrategy":"validation","validationCode":"fun clampOpenAt(openAt: Month?, start: Month, end: Month): Month? = when {\n  openAt == null -> null\n  openAt > end -> end\n  openAt < start -> start\n  else -> openAt\n}\n\nval constraints = CalendarConstraints.Builder()\n    .setStart(start).setEnd(end).setOpenAt(clampOpenAt(saved, start, end)).build()","typeGuard":null,"tryCatchPattern":null,"preventionTips":["For pickers that cap dates at 'today', compute openAt from the same cap, not from a stored selection.","Re-check bounds whenever constraints change between sessions.","Prefer omitting setOpenAt over guessing a value."],"tags":["android","material-components","datepicker","validation","calendar"],"backgroundTag":null,"analyzedSha":"ac7e18efeefb331850c561faf9ab8bf81d27ba68","analyzedAt":"2026-08-14T15:35:35.735Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}