material-components/material-components-android · error · IllegalStateException

minSeparation(%s) must be greater or equal and a multiple of

Error message

minSeparation(%s) must be greater or equal and a multiple of stepSize(%s) when using stepSize(%s)

What it means

Thrown by validateMinSeparation() in discrete mode when minSeparation (in value units) is smaller than stepSize or is not an exact multiple of stepSize. Since thumbs snap to ticks, a separation that does not align with ticks cannot be enforced, so the combination is rejected at layout time.

Source

Thrown at lib/java/com/google/android/material/slider/BaseSlider.java:768

            String.format(EXCEPTION_ILLEGAL_DISCRETE_VALUE, value, valueFrom, stepSize, stepSize));
      }
    }
  }

  private void validateMinSeparation() {
    final float minSeparation = getMinSeparation();
    if (minSeparation < 0) {
      throw new IllegalStateException(
          String.format(EXCEPTION_ILLEGAL_MIN_SEPARATION, minSeparation));
    }
    if (stepSize > 0 && minSeparation > 0) {
      if (separationUnit != UNIT_VALUE) {
        throw new IllegalStateException(
            String.format(
                EXCEPTION_ILLEGAL_MIN_SEPARATION_STEP_SIZE_UNIT, minSeparation, stepSize));
      }
      if (minSeparation < stepSize || !isMultipleOfStepSize(minSeparation)) {
        throw new IllegalStateException(
            String.format(
                EXCEPTION_ILLEGAL_MIN_SEPARATION_STEP_SIZE, minSeparation, stepSize, stepSize));
      }
    }
  }

  private void warnAboutFloatingPointError() {
    if (stepSize == 0) {
      // Only warn if slider uses a step value.
      return;
    }

    if ((int) stepSize != stepSize) {
      Log.w(TAG, String.format(WARNING_FLOATING_POINT_ERROR, "stepSize", stepSize));
    }

    if ((int) valueFrom != valueFrom) {
      Log.w(TAG, String.format(WARNING_FLOATING_POINT_ERROR, "valueFrom", valueFrom));

View on GitHub (pinned to ac7e18efee)

Solutions

  1. Round minSeparation up to the next multiple of stepSize: ((int)(minSep / step) + 1) * step when there is a remainder.
  2. At minimum use minSeparation = stepSize.
  3. If exact separation matters more than snapping, drop stepSize and use continuous mode.
  4. Recompute separation whenever stepSize changes.

Example fix

// before
slider.setStepSize(5f);
slider.setMinSeparation(3f); // 3 < 5 and not a multiple -> throws

// after
slider.setStepSize(5f);
slider.setMinSeparation(5f); // equal to and a multiple of stepSize
Defensive patterns

Strategy: validation

Validate before calling

static float alignSeparationToStep(float minSep, float step) {
  if (step <= 0f) return minSep;
  float k = (float) Math.ceil(minSep / step);
  return k * step; // >= step and an exact multiple
}
slider.setMinSeparation(alignSeparationToStep(3f, 5f)); // -> 5f

Prevention

When it happens

Trigger: stepSize > 0 and minSeparation > 0 with minSeparation < stepSize (e.g. stepSize=5, minSeparation=3), or minSeparation not a multiple (e.g. stepSize=5, minSeparation=7).

Common situations: Design specs asking for 'thumbs at least 3 apart' on a slider with stepSize 5; reusing minSeparation values after increasing stepSize.

Related errors


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