petkaantonov/bluebird · error · TypeError

expecting a function but got %s

Error message

expecting a function but got %s

What it means

Promise.coroutine.addYieldHandler(fn) registers a handler deciding what happens when a non-promise value is yielded inside a coroutine. It requires fn to be a function and throws TypeError('expecting a function but got %s') otherwise.

Source

Thrown at src/generators.js:213

        throw new TypeError(NOT_GENERATOR_ERROR);
    }
    var yieldHandler = Object(options).yieldHandler;
    var PromiseSpawn$ = PromiseSpawn;
    var stack = new Error().stack;
    return function () {
        var generator = generatorFunction.apply(this, arguments);
        var spawn = new PromiseSpawn$(undefined, undefined, yieldHandler,
                                      stack);
        var ret = spawn.promise();
        spawn._generator = generator;
        spawn._promiseFulfilled(undefined);
        return ret;
    };
};

Promise.coroutine.addYieldHandler = function(fn) {
    if (typeof fn !== "function") {
        throw new TypeError(FUNCTION_ERROR + util.classString(fn));
    }
    yieldHandlers.push(fn);
};

Promise.spawn = function (generatorFunction) {
    debug.deprecated("Promise.spawn()", "Promise.coroutine()");
    //Return rejected promise because Promise.spawn is semantically
    //something that will be called at runtime with possibly dynamic values
    if (typeof generatorFunction !== "function") {
        return apiRejection(NOT_GENERATOR_ERROR);
    }
    var spawn = new PromiseSpawn(generatorFunction, this);
    var ret = spawn.promise();
    spawn._run(Promise.spawn);
    return ret;
};
};

View on GitHub (pinned to c220cfe480)

Solutions

  1. Pass an actual function: Promise.coroutine.addYieldHandler(value => handle(value))
  2. Verify the identifier is a defined function before registering (typeof fn === 'function')
  3. Register the yield handler once at startup before creating coroutines
  4. Check for typos or arguments accidentally omitted in the call

Example fix

// before
Promise.coroutine.addYieldHandler(thunk); // thunk undefined
// after
Promise.coroutine.addYieldHandler(value =>
  value && typeof value.then === 'function' ? value : Promise.resolve(value)
);
Defensive patterns

Strategy: type-guard

Validate before calling

const handler = value => Promise.resolve(value);
if (typeof handler !== 'function') throw new TypeError('yield handler must be a function');
Promise.coroutine.addYieldHandler(handler);

Type guard

function isValidYieldHandler(fn) {
  return typeof fn === 'function' && fn.length <= 1;
}

Try / catch

try {
  Promise.coroutine.addYieldHandler(myHandler);
} catch (e) {
  if (String(e.message).startsWith('expecting a function')) {
    console.error('myHandler is not a function:', typeof myHandler);
  } else throw e;
}

Prevention

When it happens

Trigger: Promise.coroutine.addYieldHandler(undefined/null/object) — typically passing a variable that is undefined due to a bad import, forgetting the callback argument, or passing the handled value instead of a handler function.

Common situations: Misconfigured imports in refactorings; conditional code paths where the handler variable was never assigned; copying examples and leaving a placeholder argument; passing a class instead of an instance method bound function.

Related errors


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