Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RangeError: Maximum call stack exceeded #1326

Closed
kanthoney opened this issue Jan 20, 2017 · 9 comments

Comments

@kanthoney
Copy link

commented Jan 20, 2017

bluebird v3.4.7 on linux nodejs 6.9.4

The following test code produces a RangeError:

'use strict';

const Promise = require('bluebird');

const f = function*(n)
{
  for(let i = 0; i < n; i++) {
    yield i;
  }
};

Promise.each(f(2000),
             (i) => {
               if(i % 1700 === 0) {
                 return Promise.delay(1);
               }
               // Uncommenting the following line stops the error
               //return Promise.delay(1);
             });
@kanthoney

This comment has been minimized.

Copy link
Author

commented Jan 21, 2017

So the chain of events seems to be:

When return Promise.delay(1); is executed, _fulfill (line 623 of promise.js) is called. The value has the asyncGuaranteed bit set, so this._settlePromises is called (line 636). Execution winds its way through to line 566 in _settlePromise:

if (asyncGuaranteed) promise._setAsyncGuaranteed();

where the next value in the chain has its asyncGuaranteed bit set. Eventually line 431 in _resolveCallback is reached:

if (!(maybePromise instanceof Promise)) return this._fulfill(value);

where, because the next value in the chain isn't a promise, _fulfill is called again without having returned from the previous call to _fulfill. Since the current value has had its asyncGuaranteed bit set, that causes the same thing to happen with the next value and you get a huge stack of _fulfill calls.

I don't know what the asyncGuaranteed bit is for, but I would guess that the line that sets the bit for the next value in the chain is only intended to set it for the next one and isn't supposed to propogate it down the entire chain?

@xhronos

This comment has been minimized.

Copy link

commented Feb 8, 2017

I saw the same issue and stripped the problem down to this code snippet:

Promise.each(new Array(10000),(a,ix)=>{`
  if (ix===0) return Promise.delay(0);
});

The Maximum call stack size exceeded problem seems to occur with long promise chains, which includes a mix of synchronous and asynchronous promise handling.
The snippet uses Promise.each() on an array, where the first fulfillment is via Promise.delay() and the rest being fulfilled with no asynchronous calls involved. This creates a huge stack and throws RangeError: Maximum call stack size exceeded

/home/user/node/node_modules/bluebird/js/release/promise.js:519
        promise._rejectCallback(x.e, false);
                ^

RangeError: Maximum call stack size exceeded
    at Promise._settlePromiseFromHandler (/home/user/node/node_modules/bluebird/js/release/promise.js:519:17)
    at Promise._settlePromise (/home/user/node/node_modules/bluebird/js/release/promise.js:567:18)
    at Promise._settlePromise0 (/home/user/node/node_modules/bluebird/js/release/promise.js:612:10)
    at Promise._settlePromises (/home/user/node/node_modules/bluebird/js/release/promise.js:691:18)
    at Promise._fulfill (/home/user/node/node_modules/bluebird/js/release/promise.js:636:18)
    at Promise._resolveCallback (/home/user/node/node_modules/bluebird/js/release/promise.js:431:57)
    at Promise._settlePromiseFromHandler (/home/user/node/node_modules/bluebird/js/release/promise.js:522:17)
...
(many repetitions)
...
    at Promise._settlePromiseFromHandler (/home/user/node/node_modules/bluebird/js/release/promise.js:522:17)
    at Promise._settlePromise (/home/user/node/node_modules/bluebird/js/release/promise.js:567:18)
    at Promise._settlePromise0 (/home/user/node/node_modules/bluebird/js/release/promise.js:612:10)
    at Promise._settlePromises (/home/user/node/node_modules/bluebird/js/release/promise.js:691:18)
    at Promise._fulfill (/home/user/node/node_modules/bluebird/js/release/promise.js:636:18)
    at Timeout._onTimeout (/home/user/node/node_modules/bluebird/js/release/timers.js:26:46)
    at ontimeout (timers.js:365:14)
    at tryOnTimeout (timers.js:237:5)
    at Timer.listOnTimeout (timers.js:207:5)

As a workaround you would have to make all fulfillments via Promise.delay() (as you stated in your example) or via return Promise.fromCallback(setImmediate).

@richard-livingston

This comment has been minimized.

Copy link

commented Mar 6, 2017

The error also occurs in Chrome browser, version 56.0.2924.87 (64-bit) (and probably other versions)

@lastperson

This comment has been minimized.

Copy link

commented Jun 3, 2017

Have the same problem with Promise.reduce.

@martinj

This comment has been minimized.

Copy link

commented Jun 14, 2017

I also got this problem with Promise.mapSeries. I guess it affects all functions that supports Iterable.

@themauveavenger

This comment has been minimized.

Copy link

commented Apr 6, 2018

Has there been any movement on this?

@Mobe91

This comment has been minimized.

Copy link

commented Sep 11, 2018

Having the same issue using v3.5.1.

@Dzenly

This comment has been minimized.

Copy link

commented Sep 19, 2018

Why you need any movement here in 2018, everybody use async / await :)

@Mobe91

This comment has been minimized.

Copy link

commented Sep 20, 2018

@Dzenly I am using async / await but I still need bluebird for IE11.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
9 participants
You can’t perform that action at this time.