dianping/cat · error · TypeError

{fun} is not a function

Error message

{fun} is not a function

What it means

This TypeError comes from the ES5 shim bundled into worker-xquery.js: a fallback Array.prototype.reduce installed only when the environment lacks native reduce. It throws when the first argument is not callable ('fun + " is not a function"'), matching the ES5 requirement that reduce's callback be a function. In modern browsers the native method is used, but the identical error still occurs with the same cause.

Source

Thrown at cat-home/src/main/webapp/assets/js/editor/worker-xquery.js:49105

        }

        for (var i = 0; i < length; i++) {
            if (i in self && fun.call(thisp, self[i], i, object)) {
                return true;
            }
        }
        return false;
    };
}
if (!Array.prototype.reduce) {
    Array.prototype.reduce = function reduce(fun /*, initial*/) {
        var object = toObject(this),
            self = splitString && _toString(this) == "[object String]" ?
                this.split("") :
                object,
            length = self.length >>> 0;
        if (_toString(fun) != "[object Function]") {
            throw new TypeError(fun + " is not a function");
        }
        if (!length && arguments.length == 1) {
            throw new TypeError("reduce of empty array with no initial value");
        }

        var i = 0;
        var result;
        if (arguments.length >= 2) {
            result = arguments[1];
        } else {
            do {
                if (i in self) {
                    result = self[i++];
                    break;
                }
                if (++i >= length) {
                    throw new TypeError("reduce of empty array with no initial value");
                }

View on GitHub (pinned to e815e74d4c)

Solutions

  1. Pass an actual function: arr.reduce(function(acc, v) { return acc + v; }, 0).
  2. If the callback is optional/conditional, default it: cb = cb || function(x) { return x; }.
  3. Check for typos in the callback name and confirm it is defined before the reduce call.

Example fix

// before
var total = items.reduce('sum', 0);

// after
var total = items.reduce(function(acc, v) { return acc + v; }, 0);
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof callback !== 'function') {
  throw new Error('reduce callback must be a function, got ' + typeof callback);
}

Type guard

function isFunction(v) { return typeof v === 'function'; }

Try / catch

if (e instanceof TypeError && /is not a function/.test(e.message)) {
  reportUsageError('reduce', e); // point at the offending call site
}

Prevention

When it happens

Trigger: Calling array.reduce(null), array.reduce('sum'), array.reduce(someUndefined), or passing a property that is not a function (e.g. obj.callback where callback is missing) inside the worker or any code it loads.

Common situations: Passing an undefined method name; conditionally defined callbacks (if (x) cb = ...) that end up undefined; API changes where reduce was added/renamed; string 'sum' instead of a function reference.

Related errors


AI-assisted analysis of dianping/cat@e815e74d4c (2026-08-14). Data as JSON: /api/errors/567af4503d40f2ee. Report an issue: GitHub.