petkaantonov/bluebird · critical · Error

No async scheduler available See http://goo.gl/MqrFmX

Error message

No async scheduler available

    See http://goo.gl/MqrFmX

What it means

Bluebird needs an asynchronous scheduler (setImmediate, MutationObserver, etc.) to run promise callbacks. `noAsyncScheduler` (src/schedule.js:5) is the fallback installed when NO scheduling primitive is detected; invoking it throws "No async scheduler available". This means the runtime platform exposes none of the supported async mechanisms.

Source

Thrown at src/schedule.js:5

"use strict";
var util = require("./util");
var schedule;
var noAsyncScheduler = function() {
    throw new Error(NO_ASYNC_SCHEDULER);
};
var NativePromise = util.getNativePromise();
// This file figures out which scheduler to use for Bluebird. It normalizes
// async task scheduling across target platforms. Note that not all JS target
// platforms come supported. The scheduler is overridable with `setScheduler`.

// Our scheduler for Node.js/io.js is setImmediate for recent
// versions of node because of macrotask semantics.
// The `typeof` check is for an edge case with nw.js.
if (util.isNode && typeof MutationObserver === "undefined") {
    var GlobalSetImmediate = global.setImmediate;
    var ProcessNextTick = process.nextTick;
    schedule = util.isRecentNode
                ? function(fn) { GlobalSetImmediate.call(global, fn); }
                : function(fn) { ProcessNextTick.call(process, fn); };
} else if (typeof NativePromise === "function" &&
           typeof NativePromise.resolve === "function") {
    var nativePromise = NativePromise.resolve();

View on GitHub (pinned to c220cfe480)

Solutions

  1. Set a scheduler explicitly: `Promise.setScheduler(fn => setTimeout(fn, 0))`.
  2. Polyfill a scheduling primitive (e.g. setImmediate or Promise) before loading Bluebird.
  3. Update the environment/runtime to one with native scheduling support; check bundler config isn't stripping globals.

Example fix

// before
const Promise = require('bluebird');
// after
const Promise = require('bluebird');
if (typeof setImmediate === 'undefined') {
  Promise.setScheduler((fn) => setTimeout(fn, 0));
}
Defensive patterns

Strategy: fallback

Validate before calling

const hasScheduler = typeof setImmediate === 'function' ||
  typeof setTimeout === 'function' ||
  typeof MutationObserver === 'function' ||
  typeof MessageChannel === 'function';
if (!hasScheduler) {
  Promise.setScheduler((fn) => { fn(); }); // last-resort sync fallback (cooperative)
}

Type guard

const hasAsyncScheduling = () => typeof setImmediate === 'function' || typeof setTimeout === 'function';

Try / catch

try {
  const p = Promise.resolve(1); await p;
} catch (e) {
  if (String(e).includes('No async scheduler')) {
    Promise.setScheduler((fn) => setTimeout(fn, 0));
  } else throw e;
}

Prevention

When it happens

Trigger: Running in a sandboxed/locked-down environment (some WebViews, restricted workers, odd embedded JS engines) where setImmediate, MessageChannel, MutationObserver, and setTimeout-based fallbacks are all unavailable or stripped.

Common situations: Bundled code with aggressive polyfill stripping; exotic environments (React Native older builds, sandboxed eval contexts, custom JS engines); CSP blocking MutationObserver-style tricks.

Related errors


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