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
- Set a scheduler explicitly: `Promise.setScheduler(fn => setTimeout(fn, 0))`.
- Polyfill a scheduling primitive (e.g. setImmediate or Promise) before loading Bluebird.
- 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
- Smoke-test promise scheduling early in exotic environments.
- Call Promise.setScheduler with a setTimeout fallback in sandboxed runtimes.
- Check bundler/CSP settings that strip or block scheduling globals.
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.