material-components/material-components-android · error · IllegalStateException
The stepSize(%s) must be 0, or a factor of the valueFrom(%s)
Error message
The stepSize(%s) must be 0, or a factor of the valueFrom(%s)-valueTo(%s) range
What it means
BaseSlider.validateStepSize() throws IllegalStateException when stepSize > 0 and valueTo is not an exact multiple of stepSize (checked with BigDecimal to avoid float rounding errors, i.e. valueLandsOnTick(valueTo) is false). The tick system requires the range valueFrom..valueTo to divide evenly into steps, otherwise ticks cannot be laid out consistently across the range.
Source
Thrown at lib/java/com/google/android/material/slider/BaseSlider.java:732
.subtract(new BigDecimal(Float.toString(valueFrom)), DECIMAL64)
.doubleValue();
return isMultipleOfStepSize(result);
}
private boolean isMultipleOfStepSize(double value) {
// We're using BigDecimal here to avoid floating point rounding errors.
double result =
new BigDecimal(Double.toString(value))
.divide(new BigDecimal(Float.toString(stepSize)), DECIMAL64)
.doubleValue();
// If the result is a whole number, it means the value is a multiple of stepSize.
return Math.abs(Math.round(result) - result) < THRESHOLD;
}
private void validateStepSize() {
if (stepSize > 0.0f && !valueLandsOnTick(valueTo)) {
throw new IllegalStateException(
String.format(EXCEPTION_ILLEGAL_STEP_SIZE, stepSize, valueFrom, valueTo));
}
}
private void validateValues() {
if (valueFrom >= valueTo) {
throw new IllegalStateException(
String.format(EXCEPTION_ILLEGAL_VALUE_FROM, valueFrom, valueTo));
}
for (Float value : values) {
if (value < valueFrom || value > valueTo) {
throw new IllegalStateException(
String.format(EXCEPTION_ILLEGAL_VALUE, value, valueFrom, valueTo));
}
if (stepSize > 0.0f && !valueLandsOnTick(value)) {
throw new IllegalStateException(
String.format(EXCEPTION_ILLEGAL_DISCRETE_VALUE, value, valueFrom, stepSize, stepSize));View on GitHub (pinned to ac7e18efee)
Solutions
- Adjust valueTo (or valueFrom) so the range is an exact multiple of stepSize — e.g. valueFrom=0, valueTo=10, stepSize=0.5.
- Or compute stepSize from the range at runtime so it always divides evenly: pick stepSize = range / n.
- Or set stepSize=0 to disable ticks entirely when a continuous slider is acceptable.
- Prefer integer-based ranges and derive display strings, avoiding float division pitfalls.
Example fix
<!-- before -->
<com.google.android.material.slider.Slider
android:valueFrom="0" android:valueTo="10.3" app:stepSize="0.5" />
<!-- after -->
<com.google.android.material.slider.Slider
android:valueFrom="0" android:valueTo="10.5" app:stepSize="0.5" /> Defensive patterns
Strategy: validation
Validate before calling
static boolean rangeDividesByStep(float from, float to, float step) {
if (step <= 0f) return true;
java.math.BigDecimal r = new java.math.BigDecimal(Float.toString(to - from))
.divide(new java.math.BigDecimal(Float.toString(step)),
java.math.MathContext.DECIMAL64);
double result = r.doubleValue();
return Math.abs(Math.round(result) - result) < 1e-4;
}
// usage
if (rangeDividesByStep(valueFrom, valueTo, stepSize)) slider.setStepSize(stepSize); Prevention
- Derive stepSize from the range (range / tickCount) instead of hardcoding both independently.
- Prefer integer-backed ranges for data-driven sliders; format for display only.
- When valueTo comes from backend data, recompute or zero out stepSize before applying it.
When it happens
Trigger: Setting app:stepSize="0.5" with valueFrom="0" and valueTo="10.3" (10.3/0.5 = 20.6, not whole); or calling setStepSize(...) at runtime with a value that doesn't divide the configured range; using float literals whose binary representation makes the division non-integral.
Common situations: Hardcoding valueTo from data (e.g. max price 10.3) while keeping a neat step like 1 or 0.5; letting a backend value define the range without adjusting stepSize; changing valueTo dynamically (slider bounds from filtering) while leaving stepSize fixed.
Related errors
- At least one value must be set
- The continuousModeTickCount(%s) must be greater than or equa
- index out of range
- 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/83f068b21986778d.
Report an issue: GitHub.