petkaantonov/bluebird · error · TypeError

The last argument to .catch() must be a function, got

Error message

The last argument to .catch() must be a function, got %s

What it means

`.catch()` (the overload taking multiple predicates) requires its LAST argument to be a handler function; the preceding arguments are predicate values/constructors matched against the rejection reason. Bluebird throws this TypeError when the final argument is anything else, because there would be no handler to invoke.

Solutions

  1. Ensure the last argument is a function: `promise.catch(TypeError, err => ...)`.
  2. If you only have one handler, call `.catch(fn)` with no predicates.
  3. Pass the function reference itself, not an invocation: `.catch(handleErr)` not `.catch(handleErr())`.

Example fix

// before
promise.catch(TypeError, err.message => console.log);
// after
promise.catch(TypeError, (err) => console.log(err.message));
Defensive patterns

Strategy: validation

Validate before calling

function safeCatch(p, ...args) {
  const last = args[args.length - 1];
  if (typeof last !== 'function') throw new TypeError('.catch() last argument must be a function');
  return p.catch(...args);
}

Type guard

const isHandler = (v) => typeof v === 'function';

Try / catch

try { p = p.catch(TypeError, handler); } catch (e) {
  if (String(e).includes('must be a function')) p = p.catch(defaultHandler);
  else throw e;
}

Prevention

When it happens

Trigger: `promise.catch(TypeError, 'oops')` (string as last arg); `promise.catch(predicate, someVar)` where someVar is undefined or not a function; mistyping `.catch(errHandler)` as `.catch(errHandler())` (passing the result of calling the handler).

Common situations: Mistakenly using Node-style `.catch(code, handler)` conventions in browser code; forgetting the handler after listing error predicates; passing an async IIFE result instead of the function itself.

Related errors


AI-assisted analysis of petkaantonov/bluebird@c220cfe480 (2026-09-02). Data as JSON: /api/errors/f237e9f3f46010a2. Report an issue: GitHub.

Appendix: source

Thrown at src/promise.js:131

Promise.prototype.caught = Promise.prototype["catch"] = function (fn) {
    var len = arguments.length;
    if (len > 1) {
        var catchInstances = new Array(len - 1),
            j = 0, i;
        for (i = 0; i < len - 1; ++i) {
            var item = arguments[i];
            if (util.isObject(item)) {
                catchInstances[j++] = item;
            } else {
                return apiRejection("Catch statement predicate: " +
                    OBJECT_ERROR + util.classString(item));
            }
        }
        catchInstances.length = j;
        fn = arguments[i];

        if (typeof fn !== "function") {
            throw new TypeError("The last argument to .catch() " +
                "must be a function, got " + util.toString(fn));
        }
        return this.then(undefined, catchFilter(catchInstances, fn, this));
    }
    return this.then(undefined, fn);
};

Promise.prototype.reflect = function () {
    return this._then(reflectHandler,
        reflectHandler, undefined, this, undefined);
};

Promise.prototype.then = function (didFulfill, didReject) {
    if (debug.warnings() && arguments.length > 0 &&
        typeof didFulfill !== "function" &&
        typeof didReject !== "function") {
        var msg = ".then() only accepts functions but was passed: " +
                util.classString(didFulfill);

View on GitHub (pinned to c220cfe480)