Repository navigation
Promise .finally gives UnhandledPromiseRejection even if .catch has been used. #28636
Description
Activity
That is how promises work. You defined
catchandfinallyhandlers on the same promise. The promise then follows both "paths" when resolving/rejecting. One path catches it, but the other contains onlyfinally, making the rejection pass through it, then leading to unhandled rejection. What you probably want is to definefinallyon the promise returned by thecatchcall, for example:const p = Promise.reject(new Error('BOOM')); p.catch(() => {}).finally(() => {});
Similar question was asked before: nodejs/help#1208
Reacted by Jeremiah Senkpiel, AgBorkowski, laggingreflex, Nick and August Lilleaas- addedpromisesIssues and PRs related to ECMAScript promises.Issues and PRs related to ECMAScript promises.
on Jul 12, 2019 Catch is simply to catch the errors.
As a defintion of finally, - the finally block must excute at least once in whatever situation.@Hakerh400's explanation is correct.
@targos I just ran into this and it was a really nasty surprise, had me staring at my screen thinking wtf for 30 minutes, even though I've been using promises for years and years. I think the intended behavior could be changed to be more humane.
Is there no way that node could internally flag the promise returned by
.finallysuch that it won't trigger an unhandled rejection like other promises, as long as the finally handler doesn't throw its own error? It would alleviate a lot of suffering.If there's no
catchthe original promise would still trigger an unhandled rejection as desired. But unhandled rejections coming from a non-throwing.finallydon't provide any concrete benefit that I can imagine. I think they just cause harm.Reacted by Lays Dragon and ekleninI don't know if Node.js could do something like that, but I find the behavior consistent with the equivalent synchronous code:
try { throw new Error('boom') } finally { console.log('hello') }
This will log "hello" and also leave an unhandled exception.
Reacted by Timo Tijhof@targos yes I know, but consider this difference -- unlike sync code where you only need to catch an error once, with async code you can end up having to catch the same error multiple times to prevent unhandled rejection, even if only one of those catch handlers actually needs to do anything about it.
.finally()can make the same error rear its head after you've already handled it elsewhere.I realize now, the problem can happen with
.then()too. I wish Node would just help me make sure I catch a given error at least once, rather than every place it gets "passed through" to the next link in the promise chain.Because if I create a dead-end
.finally(), I was intending to respond to errors elsewhere, so the error handler for the dead-end is guaranteed to be a no-op.Reacted by Lays Dragon
Version: v12.6.0 (but 10+ also has same behaviour)
Platform: Linux sf2 4.15.0-52-generic #56-Ubuntu SMP Tue Jun 4 22:49:08 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
Subsystem:Promises
If one use promise.finally(..), it leads to unhandled promise rejection warning despite the .catch(..) handler also used.
Example code:
const p = Promise.reject(new Error('BOOM'));p.catch(() => {});p.finally(() => {});Output:
(node:22503) UnhandledPromiseRejectionWarning: Error: BOOM at Object.<anonymous> (/home/user/other/t1/t.js:25:26) at Module._compile (internal/modules/cjs/loader.js:776:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:787:10) at Module.load (internal/modules/cjs/loader.js:643:32) at Function.Module._load (internal/modules/cjs/loader.js:556:12) at Function.Module.runMain (internal/modules/cjs/loader.js:839:10) at internal/main/run_main_module.js:17:11 (node:22503) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 3) (node:22503) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.If you comment last line with .finally handler, no warnings issued.