material-components/material-components-android · error · IllegalArgumentException
Unexpected labelBehavior:
Error message
Unexpected labelBehavior:
What it means
IllegalArgumentException thrown in the label-show/hide dispatch switch when labelBehavior is not one of LABEL_GONE, LABEL_FLOATING, or LABEL_WITHIN_BOUNDS. Like the tick mode switch, this default arm is only reachable when a non-IntDef int was forced into setLabelBehavior, and it fires during interaction/layout when labels are added or removed.
Source
Thrown at lib/java/com/google/android/material/slider/BaseSlider.java:3729
ensureLabelsRemoved();
break;
case LABEL_VISIBLE:
if (isEnabled() && isSliderVisibleOnScreen()) {
ensureLabelsAdded(/* showLabelOnAllThumbs= */ true);
} else {
ensureLabelsRemoved();
}
break;
case LABEL_FLOATING:
case LABEL_WITHIN_BOUNDS:
if (activeThumbIdx != -1 && isEnabled()) {
ensureLabelsAdded(/* showLabelOnAllThumbs= */ false);
} else {
ensureLabelsRemoved();
}
break;
default:
throw new IllegalArgumentException("Unexpected labelBehavior: " + labelBehavior);
}
}
private void updateLabelPivots() {
// Set the pivot point so that the label pops up in the direction from the thumb.
final float labelPivotX;
final float labelPivotY;
final boolean isVertical = isVertical();
final boolean isRtl = isRtl();
if (isVertical && isRtl) {
labelPivotX = RIGHT_LABEL_PIVOT_X;
labelPivotY = RIGHT_LABEL_PIVOT_Y;
} else if (isVertical) {
labelPivotX = LEFT_LABEL_PIVOT_X;
labelPivotY = LEFT_LABEL_PIVOT_Y;
} else {
labelPivotX = TOP_LABEL_PIVOT_X;View on GitHub (pinned to ac7e18efee)
Solutions
- Only pass Slider.LABEL_* constants to setLabelBehavior.
- Validate and sanitize persisted ints against the known set before applying, with a sane default (LABEL_FLOATING).
- Store a stable string key instead of the raw ordinal/int value.
Example fix
// before
slider.setLabelBehavior(behaviorFromRemoteConfig); // arbitrary int
// after
int b = behaviorFromRemoteConfig;
slider.setLabelBehavior(
(b == Slider.LABEL_GONE || b == Slider.LABEL_FLOATING || b == Slider.LABEL_WITHIN_BOUNDS)
? b : Slider.LABEL_FLOATING); Defensive patterns
Strategy: validation
Validate before calling
static boolean isValidLabelBehavior(int b) {
return b == Slider.LABEL_GONE || b == Slider.LABEL_FLOATING || b == Slider.LABEL_WITHIN_BOUNDS;
}
slider.setLabelBehavior(isValidLabelBehavior(b) ? b : Slider.LABEL_FLOATING); Prevention
- Only LABEL_* constants through typed variables; avoid raw ints from remote config.
- Validate persisted behavior values on restore and default to LABEL_FLOATING.
When it happens
Trigger: setLabelBehavior(arbitraryInt) from an untyped source (prefs, Intent extra, remote config), then dragging a thumb or focusing it so ensureLabelsAdded/Removed dispatch runs.
Common situations: Persisting label behavior as a raw int across app/library versions; A/B tests or remote-config flags mapped to ints by hand.
Related errors
- Unexpected tickVisibilityMode:
- Not enough labels(%d) to display all the values(%d)
- The stepSize(%s) must be 0, or a factor of the valueFrom(%s)
- valueFrom(%s) must be smaller than valueTo(%s)
- Slider value(%s) must be greater or equal to valueFrom(%s),
AI-assisted analysis of material-components/material-components-android@ac7e18efee (2026-08-14).
Data as JSON: /api/errors/c2e1b77415440b62.
Report an issue: GitHub.