meteor/meteor · error · TypeError
Reduce of empty array with no initial value
Error message
Reduce of empty array with no initial value
What it means
Underscore's _.reduce / _.foldl / _.inject throw a TypeError with this message when the collection is empty and no initial value (memo) was supplied. With nothing to seed the accumulator, the fold is undefined; the error mirrors ES5 native Array.prototype.reduce behavior.
Source
Thrown at packages/deprecated/underscore/underscore.js:150
// **Reduce** builds up a single result from a list of values, aka `inject`,
// or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
var initial = arguments.length > 2;
if (obj == null) obj = [];
if (nativeReduce && obj.reduce === nativeReduce) {
if (context) iterator = _.bind(iterator, context);
return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
}
each(obj, function(value, index, list) {
if (!initial) {
memo = value;
initial = true;
} else {
memo = iterator.call(context, memo, value, index, list);
}
});
if (!initial) throw new TypeError(reduceError);
return memo;
};
// The right-associative version of reduce, also known as `foldr`.
// Delegates to **ECMAScript 5**'s native `reduceRight` if available.
_.reduceRight = _.foldr = function(obj, iterator, memo, context) {
var initial = arguments.length > 2;
if (obj == null) obj = [];
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
if (context) iterator = _.bind(iterator, context);
return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
}
var length = obj.length;
if (!looksLikeArray(obj)) {
var keys = _.keys(obj);
length = keys.length;
}
each(obj, function(value, index, list) {View on GitHub (pinned to 5076d2f818)
Solutions
- Pass an explicit initial value as the third argument: _.reduce(arr, fn, initialValue).
- Guard the call: if (arr.length) _.reduce(arr, fn) else useDefault().
- Use native arr.reduce(fn, seed) with a seed, which behaves identically and avoids the throw.
Example fix
// before const total = _.reduce(items, (m, x) => m + x.value, 0); // but somewhere else: _.reduce(items, (m, x) => m + x); // no seed, empty items throws // after const total = _.reduce(items, (m, x) => m + x.value, 0); // seed 0
Defensive patterns
Strategy: validation
Validate before calling
function reduceSafe(arr, fn, seed) {
if (arguments.length < 3) {
if (!arr || (arr.length !== undefined ? arr.length === 0 : _.keys(arr).length === 0)) {
throw new TypeError('Reduce of empty array with no initial value');
}
}
return _.reduce.apply(null, arguments);
} Type guard
function hasInitialValue(args) {
return args.length > 2;
} Prevention
- Always pass an explicit seed to _.reduce.
- Guard reductions over potentially-empty filtered lists.
- Prefer native arr.reduce(fn, seed) with a seed.
When it happens
Trigger: Calling _.reduce([], fn) or _.reduce(obj, fn) where obj has no enumerable values and omitting the third memo argument.
Common situations: Reducing over a query/filter result that can be empty; refactoring code that previously always had data; chaining _.reduce after _.filter that yields zero items.
Related errors
- You must provide a valid topic to publish.
- You must provide a valid topic to create a subscription.
- You must provide a valid topic to remove a subscription.
- Invalid AppCache config option: ${option}
- Can't add an invalid model to a collection
AI-assisted analysis of meteor/meteor@5076d2f818 (2026-08-13).
Data as JSON: /api/errors/6aeb1b9a0207e4dd.
Report an issue: GitHub.