{"record":{"id":"9eca2a93bd8bd6b4","repo":"material-components/material-components-android","slug":"currentpage-cannot-be-after-lastpage","errorCode":null,"errorMessage":"currentPage cannot be after lastPage","messagePattern":"currentPage cannot be after lastPage","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"lib/java/com/google/android/material/datepicker/MonthsPagerAdapter.java","lineNumber":84,"sourceCode":"  @Nullable private Month visibleMonth;\n  @KeyboardFocusDirection private int keyboardFocusDirection = POSITION_UNSPECIFIED;\n\n  MonthsPagerAdapter(\n      @NonNull Context context,\n      DateSelector<?> dateSelector,\n      @NonNull CalendarConstraints calendarConstraints,\n      @Nullable DayViewDecorator dayViewDecorator,\n      OnDayClickListener onDayClickListener,\n      @Nullable MaterialCalendar.OnMonthNavigationListener onMonthNavigationListener) {\n    Month firstPage = calendarConstraints.getStart();\n    Month lastPage = calendarConstraints.getEnd();\n    Month currentPage = calendarConstraints.getOpenAt();\n\n    if (firstPage.compareTo(currentPage) > 0) {\n      throw new IllegalArgumentException(\"firstPage cannot be after currentPage\");\n    }\n    if (currentPage.compareTo(lastPage) > 0) {\n      throw new IllegalArgumentException(\"currentPage cannot be after lastPage\");\n    }\n\n    int daysHeight = MonthAdapter.MAXIMUM_WEEKS * MaterialCalendar.getDayHeight(context);\n    int labelHeight =\n        MaterialDatePicker.isFullscreen(context) ? MaterialCalendar.getDayHeight(context) : 0;\n\n    this.itemHeight = daysHeight + labelHeight;\n    this.calendarConstraints = calendarConstraints;\n    this.dateSelector = dateSelector;\n    this.dayViewDecorator = dayViewDecorator;\n    this.onDayClickListener = onDayClickListener;\n    this.onMonthNavigationListener = onMonthNavigationListener;\n    this.visibleMonth = currentPage;\n    setHasStableIds(true);\n  }\n\n  public static class ViewHolder extends RecyclerView.ViewHolder {\n","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/material-components/material-components-android/blob/ac7e18efeefb331850c561faf9ab8bf81d27ba68/lib/java/com/google/android/material/datepicker/MonthsPagerAdapter.java#L66-L102","documentation":"MonthsPagerAdapter validates that the month the date picker opens at (CalendarConstraints.getOpenAt(), the currentPage) does not fall after the last selectable month (getEnd(), lastPage). An openAt beyond end would place the initial page outside the legal paging range, so the constructor throws IllegalArgumentException.","triggerScenarios":"CalendarConstraints.Builder().setOpenAt(openMs).setEnd(endMs) with openMs in a Month after endMs (e.g. openAt = December 2026, end = June 2026). Also triggered when end is defaulted to today's month but openAt is set to a future month, or when end/openAt are swapped by mistake.","commonSituations":"Letting users pick a future 'open at' month while capping end at today; timezone differences pushing a month boundary; refactors that reorder builder calls and accidentally exchange the end and openAt arguments.","solutions":["Clamp openAt into the range: openAt = Math.max(start, Math.min(end, openAt)) before calling setOpenAt().","If the picker should open at the latest allowed month, just omit setOpenAt() or set it equal to end.","Verify setEnd() receives milliseconds and a value >= setStart(); log the three timestamps during development to catch unit mix-ups."],"exampleFix":"// before\nnew CalendarConstraints.Builder()\n    .setStart(start)\n    .setOpenAt(target) // target > end -> crash\n    .setEnd(end)\n    .build();\n\n// after\nnew CalendarConstraints.Builder()\n    .setStart(start)\n    .setOpenAt(Math.min(target, end))\n    .setEnd(end)\n    .build();","handlingStrategy":"validation","validationCode":"long openAtClamped = Math.max(startMillis, Math.min(endMillis, openAtMillis));\nCalendarConstraints constraints = new CalendarConstraints.Builder()\n    .setStart(startMillis).setEnd(endMillis).setOpenAt(openAtClamped).build();","typeGuard":null,"tryCatchPattern":"try { pickerBuilder.setCalendarConstraints(constraints).build(); } catch (IllegalArgumentException e) { constraints = new CalendarConstraints.Builder().setStart(start).setEnd(end).build(); /* no openAt */ }","preventionTips":["Never set openAt later than end; if in doubt omit openAt.","Write a unit test: for random (start, openAt, end) triples, assert the clamped builder never throws.","Treat end < start as a config bug and assert it in debug builds."],"tags":["material-components","datepicker","calendar-constraints","validation"],"backgroundTag":null,"analyzedSha":"ac7e18efeefb331850c561faf9ab8bf81d27ba68","analyzedAt":"2026-08-14T15:35:35.735Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}