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

Invalid end icon mode:

Error message

Invalid end icon mode: 

What it means

EndCompoundLayout.getIconResId/getEndIconDelegate maps the endIconMode int to a delegate class with a switch over the END_ICON_* constants (PASSWORD_TOGGLE, CLEAR_TEXT, DROPDOWN_MENU, CUSTOM, NONE). Any int outside that set falls through to default and throws IllegalArgumentException('Invalid end icon mode: N').

Source

Thrown at lib/java/com/google/android/material/textfield/EndCompoundLayout.java:857

        delegates.append(endIconMode, delegate);
      }
      return delegate;
    }

    private EndIconDelegate create(@EndIconMode int endIconMode) {
      switch (endIconMode) {
        case END_ICON_PASSWORD_TOGGLE:
          return new PasswordToggleEndIconDelegate(endLayout, passwordIconDrawableId);
        case END_ICON_CLEAR_TEXT:
          return new ClearTextEndIconDelegate(endLayout);
        case END_ICON_DROPDOWN_MENU:
          return new DropdownMenuEndIconDelegate(endLayout);
        case END_ICON_CUSTOM:
          return new CustomEndIconDelegate(endLayout);
        case END_ICON_NONE:
          return new NoEndIconDelegate(endLayout);
        default:
          throw new IllegalArgumentException("Invalid end icon mode: " + endIconMode);
      }
    }
  }
}

View on GitHub (pinned to ac7e18efee)

Solutions

  1. Use only TextInputLayout.END_ICON_* constants when calling setEndIconMode.
  2. Validate/normalize persisted ints to a known constant before setting (default to END_ICON_NONE).
  3. Match constant usage to your Material library version.

Example fix

// before
til.setEndIconMode(modeFromConfig); // e.g. 42 -> throws

// after
int mode = (modeFromConfig >= TextInputLayout.END_ICON_NONE
    && modeFromConfig <= TextInputLayout.END_ICON_DROPDOWN_MENU)
        ? modeFromConfig : TextInputLayout.END_ICON_NONE;
til.setEndIconMode(mode);
Defensive patterns

Strategy: type-guard

Validate before calling

private static final Set<Integer> VALID_END_ICON_MODES = Set.of(
    TextInputLayout.END_ICON_NONE,
    TextInputLayout.END_ICON_CUSTOM,
    TextInputLayout.END_ICON_PASSWORD_TOGGLE,
    TextInputLayout.END_ICON_CLEAR_TEXT,
    TextInputLayout.END_ICON_DROPDOWN_MENU);

if (VALID_END_ICON_MODES.contains(mode)) til.setEndIconMode(mode);

Type guard

private boolean isValidEndIconMode(int mode) {
  return mode >= TextInputLayout.END_ICON_NONE && mode <= TextInputLayout.END_ICON_DROPDOWN_MENU;
}

Prevention

When it happens

Trigger: Calling setEndIconMode(rawInt) with a value not in the IntDef set, e.g. 0 from an uninitialized variable or a persisted value from an incompatible version; invalid app:endIconMode enum string in XML is caught earlier, so code paths dominate.

Common situations: Storing the mode as an int (settings, deep link extras) and passing it unchecked; using a constant name that exists in a newer Material version than the one on the classpath.

Related errors


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