material-components/material-components-android · error · IllegalArgumentException
%1$s must have its Adapter set to a %2$s
Error message
%1$s must have its Adapter set to a %2$s
What it means
MaterialCalendarGridView (the grid inside MaterialDatePicker) requires its ListAdapter to be a MonthAdapter so it can drive day cells, selectors and navigation. setAdapter is final and throws IllegalArgumentException, formatted with the class names, when given any other adapter type. The message reads '%1$s must have its Adapter set to a %2$s' after String.format.
Source
Thrown at lib/java/com/google/android/material/datepicker/MaterialCalendarGridView.java:236
// If no next focusable item in this month, return false to let the system move focus
// out of the GridView.
return false;
}
setSelection(nextPosition);
return true;
}
@NonNull
@Override
public MonthAdapter getAdapter() {
return (MonthAdapter) super.getAdapter();
}
@Override
public final void setAdapter(ListAdapter adapter) {
if (!(adapter instanceof MonthAdapter)) {
throw new IllegalArgumentException(
String.format(
"%1$s must have its Adapter set to a %2$s",
MaterialCalendarGridView.class.getCanonicalName(),
MonthAdapter.class.getCanonicalName()));
}
super.setAdapter(adapter);
}
private void ensureFocusRingSelector(MonthAdapter monthAdapter) {
Drawable selector = getSelector();
if (selector instanceof FocusRingDrawable) {
return;
}
Drawable drawable = FocusRingDrawable.wrap(getContext(), selector);
if (drawable instanceof FocusRingDrawable) {
FocusRingDrawable focusRingDrawable = (FocusRingDrawable) drawable;
if (monthAdapter.calendarStyle != null) {View on GitHub (pinned to ac7e18efee)
Solutions
- Do not set a foreign adapter on MaterialCalendarGridView; let MaterialDatePicker manage it.
- If you subclass, subclass MonthAdapter and keep it compatible (it drives day rendering contracts).
- In test/tooling code that touches all adapters, skip views inside MaterialDatePicker.
Example fix
// before gridView.adapter = MyCustomAdapter(items) // not a MonthAdapter -> throws // after class MyMonthAdapter(month: Month, selector: DateSelector<Long>) : MonthAdapter(month, selector) gridView.adapter = MyMonthAdapter(month, selector)
Defensive patterns
Strategy: type-guard
Validate before calling
fun setAdapterSafely(grid: AbsListView, adapter: ListAdapter) {
if (grid is MaterialCalendarGridView && adapter !is MonthAdapter) return
grid.adapter = adapter
} Type guard
fun supportsAdapter(grid: AbsListView, adapter: ListAdapter): Boolean =
!(grid is MaterialCalendarGridView && adapter !is MonthAdapter) Prevention
- Treat MaterialCalendarGridView.setAdapter as internal to MaterialDatePicker.
- In UI test/screenshot harnesses, skip adapter manipulation inside date pickers.
- Subclass MonthAdapter, never replace it, when customizing day cells.
When it happens
Trigger: Calling gridView.setAdapter(anyNonMonthAdapter) on a MaterialCalendarGridView; subclassing MaterialDatePicker internals and injecting a custom adapter; reflection-based testing tools swapping adapters on arbitrary ListViews/GridViews.
Common situations: Test frameworks (Espresso/Robotium recorders, screenshot utils) that iterate all AbsListView instances and reset adapters; custom date picker forks that reuse the grid with their own adapter.
Related errors
- start Month cannot be after current Month
- current Month cannot be after end Month
- firstDayOfWeek is not valid
- dateSelector should not be null. Use MaterialTextInputPicker
- Only Gregorian calendars are supported.
AI-assisted analysis of material-components/material-components-android@ac7e18efee (2026-08-14).
Data as JSON: /api/errors/67a7fe0c4ccb8e11.
Report an issue: GitHub.