karatelabs/karate · error · JsErrorException

Reduce of empty array with no initial value

Error message

Reduce of empty array with no initial value

What it means

Array.prototype.reduce without an initial value on an array with no elements has no seed for the accumulator, so the spec mandates a TypeError. Karate throws 'Reduce of empty array with no initial value' in its reduce implementation when the callback never ran (hasAcc still false).

Solutions

  1. Provide an initial value: arr.reduce(fn, 0) (or [], {}, as appropriate)
  2. Check the array is non-empty before reducing: if (arr.length === 0) return default;
  3. Handle empty data at the source (server returned an empty list)
  4. Catch the TypeError and return a default

Example fix

// before
const total = items.reduce((a, b) => a + b.price,);
// after
const total = items.reduce((a, b) => a + b.price, 0);
Defensive patterns

Strategy: validation

Validate before calling

if (!Array.isArray(items) || items.length === 0) return 0; // default seed

Type guard

function isNonEmptyArray(a) { return Array.isArray(a) && a.length > 0; }

Try / catch

try { return items.reduce(fn); } catch (e) { if (String(e.message).includes('Reduce of empty array')) return 0; throw e; }

Prevention

When it happens

Trigger: [].reduce(fn) or arr.reduce(fn) where arr is empty and no second (initialValue) argument is supplied.

Common situations: Summing/merging over data that turned out empty (empty JSON array from an API or empty karate response); filtering before reducing removed all elements; reduce used where reduceRight/initial value was intended.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/a550207c47cd82fc. Report an issue: GitHub.

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/JsArrayPrototype.java:893

        // is acceptable churn against the much larger
        // {@code (function(){return this.x}).reduce(...)} body of in-the-wild
        // code that depends on natural {@code this} propagation.
        JsCallable callable = requireCallable(args, "Array.prototype.reduce");
        Object thisObj = context.getThisObject();
        Object[] acc = new Object[1];
        boolean[] hasAcc = {args.length >= 2};
        if (hasAcc[0]) acc[0] = args[1];
        specIterate(context, true, true, (k, v) -> {
            if (!hasAcc[0]) {
                acc[0] = v;
                hasAcc[0] = true;
                return true;
            }
            acc[0] = callable.call(context, new Object[]{acc[0], v, k, thisObj});
            return true;
        });
        if (!hasAcc[0]) {
            throw JsErrorException.typeError("Reduce of empty array with no initial value");
        }
        return acc[0];
    }

    private Object reduceRight(Context context, Object[] args) {
        JsCallable callable = requireCallable(args, "Array.prototype.reduceRight");
        Object thisObj = context.getThisObject();
        Object[] acc = new Object[1];
        boolean[] hasAcc = {args.length >= 2};
        if (hasAcc[0]) acc[0] = args[1];
        specIterate(context, false, true, (k, v) -> {
            if (!hasAcc[0]) {
                acc[0] = v;
                hasAcc[0] = true;
                return true;
            }
            acc[0] = callable.call(context, new Object[]{acc[0], v, k, thisObj});
            return true;

View on GitHub (pinned to a22eb90246)