trekhleb/javascript-algorithms · error · Error
Items must not be empty
Error message
Items must not be empty
What it means
The second guard inside weightedRandom(): after item/weight lengths are proven equal, an empty items array is rejected because there is nothing to sample. Because the size check runs first, weightedRandom([], []) produces this message, not the size error. The function must return an {item, index} pair, which is impossible with zero candidates, so it fails fast.
Source
Thrown at src/algorithms/statistics/weighted-random/weightedRandom.js:22
*
* For example:
* - items = ['banana', 'orange', 'apple']
* - weights = [0, 0.2, 0.8]
* - weightedRandom(items, weights) in 80% of cases will return 'apple', in 20% of cases will return
* 'orange' and it will never return 'banana' (because probability of picking the banana is 0%)
*
* @param {any[]} items
* @param {number[]} weights
* @returns {{item: any, index: number}}
*/
/* eslint-disable consistent-return */
export default function weightedRandom(items, weights) {
if (items.length !== weights.length) {
throw new Error('Items and weights must be of the same size');
}
if (!items.length) {
throw new Error('Items must not be empty');
}
// Preparing the cumulative weights array.
// For example:
// - weights = [1, 4, 3]
// - cumulativeWeights = [1, 5, 8]
const cumulativeWeights = [];
for (let i = 0; i < weights.length; i += 1) {
cumulativeWeights[i] = weights[i] + (cumulativeWeights[i - 1] || 0);
}
// Getting the random number in a range of [0...sum(weights)]
// For example:
// - weights = [1, 4, 3]
// - maxCumulativeWeight = 8
// - range for the random number is [0...8]
const maxCumulativeWeight = cumulativeWeights[cumulativeWeights.length - 1];
const randomNumber = maxCumulativeWeight * Math.random();View on GitHub (pinned to 85293e3e2b)
Solutions
- Check the source of the list - it is empty at call time; log its length and the filter that produced it
- Guard the call site: if (items.length === 0) return a sensible default instead of sampling
- Fix the loader/config so the list is populated before the first draw
Example fix
// before
import weightedRandom from './src/algorithms/statistics/weighted-random/weightedRandom';
const pick = weightedRandom(prizes, prizeWeights);
// prizes and prizeWeights both [] -> throws
// after
if (prizes.length === 0) {
return null; // no prizes configured
}
const pick = weightedRandom(prizes, prizeWeights); Defensive patterns
Strategy: validation
Validate before calling
if (!Array.isArray(items) || items.length === 0) {
return null; // nothing to sample
}
weightedRandom(items, weights); Type guard
const isNonEmptyArray = (a) => Array.isArray(a) && a.length > 0;
Try / catch
try {
pick = weightedRandom(items, weights);
} catch (e) {
if (e.message === 'Items must not be empty') {
pick = null; // empty pool
} else {
throw e;
}
} Prevention
- Treat an empty candidate pool as an explicit state at the call site
- Validate config-loaded lists once at startup, not per draw
- Equal-length empties land here, not on the size error - test both
When it happens
Trigger: weightedRandom([], []); a prize/loot/name table that loaded empty because a filter removed everything, the config list is empty, or the database query returned no rows before the first draw.
Common situations: Empty configuration at first startup, over-matching filters, feature flags disabling all options, and placeholder empty arrays left in test fixtures.
Related errors
- Items and weights must be of the same size
- The method supports only positive integers
- The data is empty
- Either dataSet or labels or toClassify were not set
- Strings must be of the same length
AI-assisted analysis of trekhleb/javascript-algorithms@85293e3e2b (2026-08-24).
Data as JSON: /api/errors/a6ba06795c2288f5.
Report an issue: GitHub.