Reduce Without Initial Value

ID

javascript.reduce_without_initial_value

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

JavaScript

Tags

arrays, error-handling, reliability

Description

Reports .reduce() or .reduceRight() called with the callback alone, with no initial value for the accumulator.

Only a method call is considered — a bare reduce(fn) names some other function. A receiver written as a non-empty array literal ([1, 2, 3].reduce(sum)) is left alone: it cannot be empty, so the throw is impossible, and that shape is where starting from element zero is written deliberately. A literal holding a spread ([…​items].reduce(sum)) states nothing about the length and is still reported.

Rationale

// Bad
function totalOf(orders) {
  return orders
    .filter(order => order.paid)
    .reduce((sum, order) => sum + order.amount);
}
  • Without an initial value the first element becomes the accumulator and the callback is never called for it.

  • On an empty array there is no first element to promote, so the call throws TypeError: Reduce of empty array with no initial value. Here that happens the first time no order is paid — a crash produced by data, not by code, and therefore one that ships.

  • On a non-empty array the accumulator starts out as an element rather than as an accumulator. A reduction whose result type differs from the element type (items.reduceacc, item) ⇒ acc.concat(item) works on a one-element array and breaks on two.

Remediation

Pass the initial value. It is also where the accumulator’s type gets stated, instead of being inferred from whatever the array happens to hold.

// Good
function totalOf(orders) {
  return orders
    .filter(order => order.paid)
    .reduce((sum, order) => sum + order.amount, 0);
}

// Good — the accumulator's type is visible at the call site
const names = people.reduce((all, person) => all.concat(person.name), []);

© 2026 Xygeni. All rights reserved