petkaantonov/bluebird · error · TypeError

expecting a function but got %s

Error message

expecting a function but got %s

What it means

Thrown by the internal `check` function (src/promise.js:90) when the Promise constructor is invoked incorrectly — either called without `new`, on a subclass whose constructor identity changed, or when the executor argument is not a function. Bluebird guards its constructor so the API cannot be misused silently.

Source

Thrown at src/promise.js:90

var Context = require("./context")(Promise);
 /*jshint unused:false*/
var createContext = Context.create;

var debug = require("./debuggability")(Promise, Context,
    enableAsyncHooks, disableAsyncHooks);
var CapturedTrace = debug.CapturedTrace;
var PassThroughHandlerContext =
    require("./finally")(Promise, tryConvertToPromise, NEXT_FILTER);
var catchFilter = require("./catch_filter")(NEXT_FILTER);
var nodebackForPromise = require("./nodeback");
var errorObj = util.errorObj;
var tryCatch = util.tryCatch;
function check(self, executor) {
    if (self == null || self.constructor !== Promise) {
        throw new TypeError(CONSTRUCT_ERROR_INVOCATION);
    }
    if (typeof executor !== "function") {
        throw new TypeError(FUNCTION_ERROR + util.classString(executor));
    }

}

function Promise(executor) {
    if (executor !== INTERNAL) {
        check(this, executor);
    }
    this._bitField = NO_STATE;
    this._fulfillmentHandler0 = undefined;
    this._rejectionHandler0 = undefined;
    this._promise0 = undefined;
    this._receiver0 = undefined;
    this._resolveFromExecutor(executor);
    this._promiseCreated();
    this._fireEvent("promiseCreated", this);
}

View on GitHub (pinned to c220cfe480)

Solutions

  1. Always call the constructor with `new`: `new Promise((resolve, reject) => ...)`.
  2. Pass a function as the executor; if you have a promise already, don't wrap it — use it directly or `Promise.resolve(x)`.
  3. If subclassing, ensure the subclass properly calls `super(executor)` and doesn't break the constructor identity.
  4. If you need a promise from a non-function value, use `Promise.resolve(value)` instead of the constructor.

Example fix

// before
const p = Promise((resolve) => resolve(1));
// after
const p = new Promise((resolve) => resolve(1));
Defensive patterns

Strategy: type-guard

Validate before calling

function safeNewPromise(executor) {
  if (typeof executor !== 'function') {
    throw new TypeError('executor must be a function, got ' + typeof executor);
  }
  return new Promise(executor);
}

Type guard

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

Try / catch

let p;
try { p = new Promise(executor); } catch (e) {
  if (e instanceof TypeError) { /* fall back to Promise.resolve(value) */ p = Promise.resolve(null); }
  else throw e;
}

Prevention

When it happens

Trigger: Calling `Promise(resolver)` without `new`; `const P = Promise; P(fn)` is fine, but calling a rebound/stolen constructor (e.g. `Promise.call(obj, fn)`) fails the `self.constructor !== Promise` check; `new Promise(nonFunction)` such as `new Promise(undefined)`.

Common situations: Forgetting `new` after refactoring; subclassing Promise and overriding constructor; passing a thenable or object instead of a resolver function; transpilers or wrappers that re-invoke the constructor.

Related errors


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