material-components/material-components-android · error · IllegalArgumentException

no button data for mode: > mode <

Error message

no button data for mode: > mode <

What it means

MaterialTimePicker.getButtonDataForMode (MaterialTimePicker.java:458) maps the picker's input mode to icon/tooltip data for the mode-toggle button. The switch only handles INPUT_MODE_KEYBOARD (0) and INPUT_MODE_CLOCK (1); any other int falls through to the default branch and throws IllegalArgumentException. This indicates the mode value was never produced by the library's own constants.

Solutions

  1. Always use the constants MaterialTimePicker.INPUT_MODE_KEYBOARD or MaterialTimePicker.INPUT_MODE_CLOCK.
  2. Validate any dynamically sourced mode: if (mode != INPUT_MODE_KEYBOARD && mode != INPUT_MODE_CLOCK) mode = INPUT_MODE_CLOCK;
  3. When persisting/restoring mode, sanitize on read with Math.max(0, Math.min(1, mode)) or an explicit whitelist check.

Example fix

// before
picker.setMode(prefs.getInt("time_mode", 3)); // 3 is invalid

// after
int mode = prefs.getInt("time_mode", MaterialTimePicker.INPUT_MODE_CLOCK);
if (mode != MaterialTimePicker.INPUT_MODE_CLOCK && mode != MaterialTimePicker.INPUT_MODE_KEYBOARD) {
  mode = MaterialTimePicker.INPUT_MODE_CLOCK;
}
picker.setMode(mode);
Defensive patterns

Strategy: validation

Validate before calling

static int sanitizeTimePickerMode(int mode) {
  return (mode == MaterialTimePicker.INPUT_MODE_KEYBOARD
          || mode == MaterialTimePicker.INPUT_MODE_CLOCK)
      ? mode
      : MaterialTimePicker.INPUT_MODE_CLOCK;
}
picker.setMode(sanitizeTimePickerMode(rawMode));

Try / catch

try { picker.setMode(mode); } catch (IllegalArgumentException e) { picker.setMode(MaterialTimePicker.INPUT_MODE_CLOCK); } // last-resort only; prefer pre-validation

Prevention

When it happens

Trigger: Calling materialTimePicker.setMode(someInt) with a value outside 0/1 and then showing the picker (the mode-toggle button is built when the picker UI is constructed); passing a mode read from bundle/state that was corrupted or hand-computed; reflection or a custom saved-state round-trip writing an invalid mode.

Common situations: Hardcoding a mode int instead of using MaterialTimePicker.INPUT_MODE_CLOCK / INPUT_MODE_KEYBOARD; persisting mode in savedInstanceState with a stale value after a library constant change; passing a value obtained from an enum ordinal of the wrong enum.

Related errors


AI-assisted analysis of material-components/material-components-android@ac7e18efee (2026-08-14). Data as JSON: /api/errors/302e0e7e848a0006. Report an issue: GitHub.

Appendix: source

Thrown at lib/java/com/google/android/material/timepicker/MaterialTimePicker.java:458

    timePickerTextInputPresenter.clearCheck();

    return timePickerTextInputPresenter;
  }

  private ModeButtonData getModeButtonData(@InputMode int mode) {
    switch (mode) {
      case INPUT_MODE_KEYBOARD:
        return new ModeButtonData(
            clockIcon,
            R.string.material_timepicker_clock_mode_description,
            R.string.material_timepicker_clock_mode_tooltip);
      case INPUT_MODE_CLOCK:
        return new ModeButtonData(
            keyboardIcon,
            R.string.material_timepicker_text_input_mode_description,
            R.string.material_timepicker_text_input_mode_tooltip);
      default:
        throw new IllegalArgumentException("no button data for mode: " + mode);
    }
  }

  @Nullable
  TimePickerClockPresenter getTimePickerClockPresenter() {
    return timePickerClockPresenter;
  }

  @VisibleForTesting
  void setActivePresenter(@Nullable TimePickerPresenter presenter) {
    activePresenter = presenter;
  }

  /** The supplied listener is called when the user confirms a valid selection. */
  public boolean addOnPositiveButtonClickListener(@NonNull OnClickListener listener) {
    return positiveButtonListeners.add(listener);
  }

View on GitHub (pinned to ac7e18efee)