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

is not a valid TabIndicatorAnimationMode

Error message

 is not a valid TabIndicatorAnimationMode

What it means

setTabIndicatorAnimationMode(int) maps the mode to an interpolator via a switch over the @TabIndicatorAnimationMode IntDef constants (LINEAR, ELASTIC, FADE). Any value outside those constants falls to default and throws IllegalArgumentException, because no interpolator exists for it.

Source

Thrown at lib/java/com/google/android/material/tabs/TabLayout.java:1233

   *     #INDICATOR_ANIMATION_MODE_ELASTIC}
   * @attr ref com.google.android.material.R.styleable#TabLayout_tabIndicatorAnimationMode
   * @see #getTabIndicatorAnimationMode()
   */
  public void setTabIndicatorAnimationMode(
      @TabIndicatorAnimationMode int tabIndicatorAnimationMode) {
    this.tabIndicatorAnimationMode = tabIndicatorAnimationMode;
    switch (tabIndicatorAnimationMode) {
      case INDICATOR_ANIMATION_MODE_LINEAR:
        this.tabIndicatorInterpolator = new TabIndicatorInterpolator();
        break;
      case INDICATOR_ANIMATION_MODE_ELASTIC:
        this.tabIndicatorInterpolator = new ElasticTabIndicatorInterpolator();
        break;
      case INDICATOR_ANIMATION_MODE_FADE:
        this.tabIndicatorInterpolator = new FadeTabIndicatorInterpolator();
        break;
      default:
        throw new IllegalArgumentException(
            tabIndicatorAnimationMode + " is not a valid TabIndicatorAnimationMode");
    }
  }

  /**
   * Get the current indicator animation mode used to animate the selection indicator between
   * destinations.
   *
   * @return one of {@link #INDICATOR_ANIMATION_MODE_LINEAR} or {@link
   *     #INDICATOR_ANIMATION_MODE_ELASTIC}
   * @attr ref com.google.android.material.R.styleable#TabLayout_tabIndicatorAnimationMode
   * @see #setTabIndicatorAnimationMode(int)
   */
  @TabIndicatorAnimationMode
  public int getTabIndicatorAnimationMode() {
    return tabIndicatorAnimationMode;
  }

View on GitHub (pinned to ac7e18efee)

Solutions

  1. Use only the declared constants: TabLayout.INDICATOR_ANIMATION_MODE_LINEAR, INDICATOR_ANIMATION_MODE_ELASTIC, INDICATOR_ANIMATION_MODE_FADE.
  2. Validate persisted/int-derived values against the constant set before calling the setter.
  3. Check XML app:tabIndicatorAnimationMode values against the supported set (linear, elastic, fade).

Example fix

// before
tabLayout.setTabIndicatorAnimationMode(modeFromServer); // e.g. 7

// after
int mode = (modeFromServer == INDICATOR_ANIMATION_MODE_ELASTIC)
    ? INDICATOR_ANIMATION_MODE_ELASTIC : INDICATOR_ANIMATION_MODE_LINEAR;
tabLayout.setTabIndicatorAnimationMode(mode);
Defensive patterns

Strategy: validation

Validate before calling

private static final Set<Integer> VALID_MODES = Set.of(
    TabLayout.INDICATOR_ANIMATION_MODE_LINEAR,
    TabLayout.INDICATOR_ANIMATION_MODE_ELASTIC,
    TabLayout.INDICATOR_ANIMATION_MODE_FADE);

private void applyMode(int mode) {
  if (VALID_MODES.contains(mode)) tabLayout.setTabIndicatorAnimationMode(mode);
}

Type guard

private boolean isValidIndicatorAnimationMode(int mode) {
  return mode == TabLayout.INDICATOR_ANIMATION_MODE_LINEAR
      || mode == TabLayout.INDICATOR_ANIMATION_MODE_ELASTIC
      || mode == TabLayout.INDICATOR_ANIMATION_MODE_FADE;
}

Prevention

When it happens

Trigger: Passing a raw int that is not one of TabLayout.INDICATOR_ANIMATION_MODE_LINEAR/ELASTIC/FADE (e.g. a typo'd constant or a value read from an unvalidated source), or setting an invalid app:tabIndicatorAnimationMode in XML.

Common situations: Storing the mode as an int in preferences/payloads and passing it back unchecked; using a constant copied from an older/newer version that does not exist in the linked library version.

Related errors


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