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
- Use only TextInputLayout.END_ICON_* constants when calling setEndIconMode.
- Validate/normalize persisted ints to a known constant before setting (default to END_ICON_NONE).
- 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
- Only pass TextInputLayout.END_ICON_* constants.
- Annotate wrapper params with @TextInputLayout.EndIconMode for compile-time checks.
- Normalize persisted ints to END_ICON_NONE by default.
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
- endIconSize cannot be less than 0
- startIconSize cannot be less than 0
- > boxBackgroundMode < is illegal; only @BoxBackgroundMode co
- There must be a keyline marked as focal.
- No color resources provided for harmonization.
AI-assisted analysis of material-components/material-components-android@ac7e18efee (2026-08-14).
Data as JSON: /api/errors/184adabc6eec2132.
Report an issue: GitHub.