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
Closed

RangeError: Maximum call stack exceeded #1326

kanthoney opened this issue Jan 20, 2017 · 9 comments

Comments

@kanthoney
Copy link

@kanthoney kanthoney 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
Copy link
Author

@kanthoney kanthoney 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
Copy link

@xhronos xhronos 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
Copy link

@richard-livingston richard-livingston commented Mar 6, 2017

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

@lastperson
Copy link

@lastperson lastperson commented Jun 3, 2017

Have the same problem with Promise.reduce.

@martinj
Copy link

@martinj martinj commented Jun 14, 2017

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

@themauveavenger
Copy link

@themauveavenger themauveavenger commented Apr 6, 2018

Has there been any movement on this?

@Mobe91
Copy link

@Mobe91 Mobe91 commented Sep 11, 2018

Having the same issue using v3.5.1.

@Dzenly
Copy link

@Dzenly Dzenly commented Sep 19, 2018

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

@Mobe91
Copy link

@Mobe91 Mobe91 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
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
10 participants