material-components/material-components-android · error · IllegalStateException
Not enough labels(%d) to display all the values(%d)
Error message
Not enough labels(%d) to display all the values(%d)
What it means
IllegalStateException thrown in the label-assignment loop when the internal label pool runs out before every thumb (ending with the focused thumb) got a label. Labels are created lazily into a pool sized by the slider itself, so in practice this is an internal invariant violation — most often seen when values were mutated without the label pool being rebuilt, or in custom subclasses that interfere with label handling.
Source
Thrown at lib/java/com/google/android/material/slider/BaseSlider.java:3832
labelsInAnimator = createLabelAnimator(true);
labelsOutAnimator = null;
labelsInAnimator.start();
}
Iterator<TooltipDrawable> labelItr = labels.iterator();
if (showLabelOnAllThumbs) {
for (int i = 0; i < values.size() && labelItr.hasNext(); i++) {
if (i == focusedThumbIdx) {
// We position the focused thumb last so it's displayed on top, so skip it for now.
continue;
}
setValueForLabel(labelItr.next(), values.get(i));
}
}
if (!labelItr.hasNext()) {
throw new IllegalStateException(
String.format(
"Not enough labels(%d) to display all the values(%d)", labels.size(), values.size()));
}
// Now set the label for the focused thumb so it's on top.
setValueForLabel(labelItr.next(), values.get(focusedThumbIdx));
}
private String formatValue(float value) {
if (hasLabelFormatter()) {
return formatter.getFormattedValue(value);
}
return String.format((int) value == value ? "%.0f" : "%.2f", value);
}
private void setValueForLabel(TooltipDrawable label, float value) {
label.setText(formatValue(value));View on GitHub (pinned to ac7e18efee)
Solutions
- Never mutate the list returned by getValues(); always call setValues() with a new list.
- In custom subclasses, delegate value changes to setValues() so dirtyConfig and the label pool stay consistent.
- If it reproduces with stock Slider, upgrade (or pin) the Material Components version and report it with the exact configuration.
Example fix
// before slider.getValues().add(5f); // in-place mutation desyncs internal label count // after List<Float> vals = new ArrayList<>(slider.getValues()); vals.add(5f); slider.setValues(vals);
Defensive patterns
Strategy: try-catch
Validate before calling
List<Float> vals = new ArrayList<>(slider.getValues()); vals.add(newValue); slider.setValues(vals); // keeps label pool in sync with value count
Try / catch
Wrap interaction-triggered show paths defensively in custom subclasses: try { slider.onDraw(...) } catch (IllegalStateException e) { Log.e(TAG, "label/value desync", e); } — but fix the root cause (never mutate getValues() in place). Prevention
- Never mutate the list returned by getValues(); build a copy and call setValues().
- In subclasses, route all value changes through setValues().
- If stock Slider hits this, pin/upgrade the Material Components version and report it.
When it happens
Trigger: Having more thumbs/values than pooled labels after in-place mutation of the values list (e.g. obtaining getValues() and modifying it), or subclassing BaseSlider and overriding label behavior/values handling inconsistently.
Common situations: Custom slider subclasses (e.g. custom RangeSlider variants) that bypass setValues(); rare version-specific regressions in the label pool logic — check the Material Components changelog if it reproduces with plain Slider usage.
Related errors
- Unexpected tickVisibilityMode:
- Unexpected labelBehavior:
- No color resources found for harmonization.
- The stepSize(%s) must be 0, or a factor of the valueFrom(%s)
- valueFrom(%s) must be smaller than valueTo(%s)
AI-assisted analysis of material-components/material-components-android@ac7e18efee (2026-08-14).
Data as JSON: /api/errors/0579cec86d0d839d.
Report an issue: GitHub.