Dogfalo/materialize · error · Error

noUiSlider: 'limit', 'margin' and 'padding' must be divisibl

Error message

noUiSlider: 'limit', 'margin' and 'padding' must be divisible by step.

What it means

Thrown by Spectrum.getMargin, which testMargin/testLimit/testPadding all call. If a step is set and value/step has a fractional remainder, the value is not on the step grid and the library refuses it so handle positions stay reachable. The check is (value / step) % 1 !== 0, which is also vulnerable to IEEE-754 rounding for decimal steps.

Source

Thrown at extras/noUiSlider/nouislider.js:400

            handleEntryPoint(ordered[index][1], ordered[index][0], this);
        }

        // Store the actual step values.
        // xSteps is sorted in the same order as xPct and xVal.
        this.xNumSteps = this.xSteps.slice(0);

        // Convert all numeric steps to the percentage of the subrange they represent.
        for ( index = 0; index < this.xNumSteps.length; index++ ) {
            handleStepPoint(index, this.xNumSteps[index], this);
        }
    }

    Spectrum.prototype.getMargin = function ( value ) {

        var step = this.xNumSteps[0];

        if ( step && ((value / step) % 1) !== 0 ) {
            throw new Error("noUiSlider: 'limit', 'margin' and 'padding' must be divisible by step.");
        }

        return this.xPct.length === 2 ? fromPercentage(this.xVal, value) : false;
    };

    Spectrum.prototype.toStepping = function ( value ) {

        value = toStepping( this.xVal, this.xPct, value );

        return value;
    };

    Spectrum.prototype.fromStepping = function ( value ) {

        return fromStepping( this.xVal, this.xPct, value );
    };

    Spectrum.prototype.getStep = function ( value ) {

View on GitHub (pinned to 824e78248b)

Solutions

  1. Make margin/limit/padding an exact integer multiple of step.
  2. For decimal steps, snap to the grid: margin = Math.round(want / step) * step.
  3. Drop the constraint (set to 0 or omit) if exact divisibility is not required.

Example fix

// before
step: 0.3, margin: 0.9   // throws: 0.9/0.3 is 2.9999...
// after
step: 0.3, margin: Math.round(0.9 / 0.3) * 0.3
Defensive patterns

Strategy: validation

Validate before calling

function snapToStep(value, step) { return step ? Math.round(value / step) * step : value; }
function assertDivisible(value, step) {
  if (step && (value / step) % 1 !== 0) throw new Error(value + ' must be a multiple of step ' + step);
}
['margin','limit','padding'].forEach(k => { if (opts[k] != null) assertDivisible(opts[k], opts.step); });

Try / catch

try { noUiSlider.create(el, opts); }
catch (e) {
  if (/divisible by step/.test(e.message)) { opts.margin = snapToStep(opts.margin, opts.step); /* retry */ }
  else throw e;
}

Prevention

When it happens

Trigger: step: 10, margin: 25 (25/10 = 2.5). step: 5, limit: 12. The classic float trap: step: 0.3, margin: 0.9, because 0.9/0.3 evaluates to 2.9999999999999996 in JS and % 1 is non-zero.

Common situations: Mixing step with margin/limit/padding expressed in different units, changing step without updating the others, or using decimal steps that hit floating-point error.

Related errors


AI-assisted analysis of Dogfalo/materialize@824e78248b (2026-08-13). Data as JSON: /api/errors/f4a234f1f8e693a3. Report an issue: GitHub.