question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

returning Promise.reject in async function results in Unhandled rejection error message

See original GitHub issue
  1. What version of bluebird is the issue happening on? 3.5.0

  2. What platform and version? (For example Node.js 0.12 or Google Chrome 32) Node.js 8.0.0 on Ubuntu

  3. Did this issue happen with earlier version of bluebird? Yes

When returning Promise.reject in async function, an error is printed on the console “Unhandled rejection” even the promise is caught. It doesn’t print out the error if native Promise is used.

const Promise = require("bluebird");

async function WaitAsync(){
    return Promise.reject(new Error("reject"));
}

Promise.resolve().then(() => {
    return WaitAsync();
}).catch(err => {
    console.log("caught: ", err);
});

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:14
  • Comments:21 (2 by maintainers)

github_iconTop GitHub Comments

14reactions
sorccucommented, Jun 12, 2017

I believe I’m encountering another instance of this issue. In fact I was going to post a new issue before I saw this one. Here’s my description:

This issue is a bit difficult to grasp, so I’ll do my best to explain with examples. It seems that when using Promise.using() with an async function, awaiting on already rejected promises always outputs an Unhandled rejection when using Bluebird’s Promise.reject(), but not when using native Promise.reject() or throw in an async function.

These code snippets are runnable directly on node 8 (tested on v8.1.0) with Bluebird v3.5.0 (and earlier).

First, let’s start from a problematic example.

// Failing example 1

const Promise = require('bluebird')

Promise.using(Promise.resolve(), async () => {
  await Promise.reject(new Error('foo'))
})
.catch(() => console.log('OK'))

This snippet, when run, produces the following output:

Unhandled rejection Error: foo
    at Promise.using (<redacted>/a.js:4:24)
    at tryCatcher (<redacted>/node_modules/bluebird/js/release/util.js:16:23)
    at <redacted>/node_modules/bluebird/js/release/using.js:185:26
    at tryCatcher (<redacted>/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (<redacted>/node_modules/bluebird/js/release/promise.js:512:31)
    at Promise._settlePromise (<redacted>/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromise0 (<redacted>/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (<redacted>/node_modules/bluebird/js/release/promise.js:693:18)
    at Promise._fulfill (<redacted>/node_modules/bluebird/js/release/promise.js:638:18)
    at PromiseArray._resolve (<redacted>/node_modules/bluebird/js/release/promise_array.js:126:19)
    at PromiseArray._promiseFulfilled (<redacted>/node_modules/bluebird/js/release/promise_array.js:144:14)
    at Promise._settlePromise (<redacted>/node_modules/bluebird/js/release/promise.js:574:26)
    at Promise._settlePromise0 (<redacted>/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (<redacted>/node_modules/bluebird/js/release/promise.js:693:18)
    at Async._drainQueue (<redacted>/node_modules/bluebird/js/release/async.js:133:16)
    at Async._drainQueues (<redacted>/node_modules/bluebird/js/release/async.js:143:10)

OK

As you can see, we have an unhandled rejection error yet we did handle the error, and no clear way of rewriting the snippet so that the unhandled rejection would not occur.

Confusingly, if we reject by using native promises, we do not get the unhandled rejection. In this snippet, we only use .using() from Bluebird.

// Working example 1

const Bluebird = require('bluebird')

Bluebird.using(Promise.resolve(), async () => {
  await Promise.reject(new Error('foo'))
})
.catch(() => console.log('OK'))

This outputs simply:

OK

Similarly, this also prints the warning:

// Failing example 2

const Promise = require('bluebird')

const reject = () => Promise.reject(new Error('foo'))

Promise.using(Promise.resolve(), async () => {
  await reject()
})
.catch(() => console.log('OK'))
Unhandled rejection Error: foo
    at reject (<redacted>/a.js:3:37)
    at Promise.using (<redacted>/a.js:6:9)
    at tryCatcher (<redacted>/node_modules/bluebird/js/release/util.js:16:23)
    at <redacted>/node_modules/bluebird/js/release/using.js:185:26
    at tryCatcher (<redacted>/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (<redacted>/node_modules/bluebird/js/release/promise.js:512:31)
    at Promise._settlePromise (<redacted>/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromise0 (<redacted>/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (<redacted>/node_modules/bluebird/js/release/promise.js:693:18)
    at Promise._fulfill (<redacted>/node_modules/bluebird/js/release/promise.js:638:18)
    at PromiseArray._resolve (<redacted>/node_modules/bluebird/js/release/promise_array.js:126:19)
    at PromiseArray._promiseFulfilled (<redacted>/node_modules/bluebird/js/release/promise_array.js:144:14)
    at Promise._settlePromise (<redacted>/node_modules/bluebird/js/release/promise.js:574:26)
    at Promise._settlePromise0 (<redacted>/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (<redacted>/node_modules/bluebird/js/release/promise.js:693:18)
    at Async._drainQueue (<redacted>/node_modules/bluebird/js/release/async.js:133:16)

OK

However, this one doesn’t:

// Working example 2

const Bluebird = require('bluebird')

const reject = () => Promise.reject(new Error('foo'))

Bluebird.using(Promise.resolve(), async () => {
  await reject()
})
.catch(() => console.log('OK'))
OK

And neither does this one:

// Working example 3

const Promise = require('bluebird')

const reject = async () => {
  throw new Error('foo')
}

Promise.using(Promise.resolve(), async () => {
  await reject()
})
.catch(() => console.log('OK'))
OK

With async/await translated to plain promises, the failing examples also work without issue:

// Previously failing example 1 (working w/o async)

const Promise = require('bluebird')

Promise.using(Promise.resolve(), () => {
  return Promise.reject(new Error('foo'))
})
.catch(() => console.log('OK'))
OK
// Previously failing example 2 (working w/o async)

const Promise = require('bluebird')

const reject = () => Promise.reject(new Error('foo'))

Promise.using(Promise.resolve(), reject)
.catch(() => console.log('OK'))
OK

This leads me to believe that there may perhaps be a bug in Bluebird, causing a rejected bluebird-promise returned by an async function to be handled asynchronously.

Thoughts?

2reactions
kjhangianicommented, Aug 4, 2017

We just got bit by this issue. We’ve just recently moved to node@8.2.1 and are using async/await extensively, along with bluebird.

I see @suguru03 has a PR to fix it, is that going to be merged soon?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Handling those unhandled promise rejections with JS async ...
You put your code inside an async function in order to use await calls; One of your await ed functions fails (i.e. rejects...
Read more >
UnhandledPromiseRejectionWar...
UnhandledPromiseRejectionWarning means that a promise weren't synchronously chained with catch , this resulted in unhandled rejection.
Read more >
Preventing unhandled promise rejections in async functions
How to prevent unhandled promise rejections when using async/ await. ... and I have observed presence of an odd error message in my...
Read more >
Testing promise rejection in JavaScript with Jest - Codeleak.pl
Let's consider a simple function that returns a Promise that can either resolve or reject depending on the value of the first argument:...
Read more >
async function - JavaScript - MDN Web Docs - Mozilla
In concurrentStart , if promise fast rejects before promise slow is fulfilled, then an unhandled promise rejection error will be raised, ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found