ankane/pghero · error · Error
noUiSlider: invalid handle number, got: {handleNumber}
Error message
noUiSlider: invalid handle number, got: {handleNumber} What it means
valueSetHandle() coerces the handle number with Number() and requires 0 <= handleNumber < scope_HandleNumbers.length (the number of handles created from the start option). API calls that address a single handle - chiefly noUiSlider.setHandle(handleNumber, value) - throw this Error when the index does not exist, including the NaN case from non-numeric input.
Source
Thrown at app/assets/javascripts/pghero/nouislider.js:2087
setZindex();
scope_HandleNumbers.forEach(function (handleNumber) {
fireEvent("update", handleNumber);
// Fire the event only for handles that received a new value, as per #579
if (values[handleNumber] !== null && fireSetEvent) {
fireEvent("set", handleNumber);
}
});
}
// Reset slider to initial values
function valueReset(fireSetEvent) {
valueSet(options.start, fireSetEvent);
}
// Set value for a single handle
function valueSetHandle(handleNumber, value, fireSetEvent, exactInput) {
// Ensure numeric input
handleNumber = Number(handleNumber);
if (!(handleNumber >= 0 && handleNumber < scope_HandleNumbers.length)) {
throw new Error("noUiSlider: invalid handle number, got: " + handleNumber);
}
// Look both backward and forward, since we don't want this handle to "push" other handles (#960);
// The exactInput argument can be used to ignore slider stepping (#436)
setHandle(handleNumber, resolveToValue(value, handleNumber), true, true, exactInput);
fireEvent("update", handleNumber);
if (fireSetEvent) {
fireEvent("set", handleNumber);
}
}
// Get the slider value.
function valueGet(unencoded) {
if (unencoded === void 0) { unencoded = false; }
if (unencoded) {
// return a copy of the raw values
return scope_Values.length === 1 ? scope_Values[0] : scope_Values.slice(0);
}
var values = scope_Values.map(options.format.to);
// If only one handle is used, return a single value.View on GitHub (pinned to 7edb57986f)
Solutions
- Check the live handle count before setting: slider.noUiSlider.get().length is the number of handles
- Use set() with an array matching the start configuration instead of setHandle when targeting all handles
- Make the handle count explicit in one place and derive both start and any setHandle indices from it
Example fix
// before - slider has one handle but index 1 requested
slider.noUiSlider.setHandle(1, 50);
// after - guard against the handle count
if (index < slider.noUiSlider.get().length) {
slider.noUiSlider.setHandle(index, 50);
} Defensive patterns
Strategy: validation
Validate before calling
const handleCount = slider.noUiSlider.get().length; // works for 1..n handles
if (handleNumber >= 0 && handleNumber < handleCount) {
slider.noUiSlider.setHandle(handleNumber, value);
} Prevention
- Derive handle indices from the start array length instead of hardcoding them
- Prefer set([...]) with the full array over setHandle when handle count may change
When it happens
Trigger: A slider created with start: [50] (one handle) followed by slider.noUiSlider.setHandle(1, 80); an index computed from data attributes or loops that goes past handle count - 1; passing undefined (Number(undefined) is NaN, which fails the range check).
Common situations: Handle count varies with configuration (start array length changes) while calling code hardcodes indices; off-by-one loops over handles; saved UI state (per-handle positions) replayed onto a slider that now has fewer handles.
Related errors
- noUiSlider: 'cssClasses' must be an object.
- noUiSlider: '{name}' is required.
- noUiSlider: 'values' (>= 2) required for mode 'count'.
- noUiSlider: create requires a single element, got: {target}
- noUiSlider: Slider was already initialized.
AI-assisted analysis of ankane/pghero@7edb57986f (2026-08-21).
Data as JSON: /api/errors/616da10f55fb495b.
Report an issue: GitHub.