How can I determine where the Promise rejection happened when I only caught it using onunhandledrejection handler?
console.error = ()=>{}
window.addEventListener('unhandledrejection', (promiseRejectionEvent) => {
console.log('unhandled: ', Error().stack)
})
function main() {
new Promise(() => { throw null })
}
main()
If you check your browser's console after running this, you will see something like:

The Error().stack only includes the rejection handler function itself in its stack trace (grey output js:14:30). But the browser does seem to know where the rejection happened: There is another red error output (Uncaught (in promise) null), pointing to the target line (js:18). How can I access this line information?
It seems that the latter output is being done by the browser's internals, as it is not preventable by overwriting console.error like in the example above. It is only preventable by calling promiseRejectionEvent.preventDefault(), as explained on MDN. But I don't want to prevent it anyway, but retrieve it instead, for example for logging purposes.
Real world use case: It would of course be possible to not rely on onunhandledrejection event handler, e.g. by adding a .catch() phrase or at least throwing throw new Error(null). But in my case, I have no control over it as it is third party code. It threw unexpectedly today (probably a library bug) at a client's browser and the automatic error report did not include a stack trace. I tried to narrow down the underlying issue above. Thanks!
Edit in response to comments:
Wrap the third party code in a try/catch? – weltschmerz
Good point, but this does not help because the rejection actually happens inside a callback:
window.addEventListener('unhandledrejection', (promiseRejectionEvent) => {
console.log('unhandled: ', Error().stack) // <- stack once again does *not* include "main()", it is only printed out in the console
})
function main() {
try {
thirdPartyModule()
} catch(e) {
// Never caught
console.log("caught:", e)
}
}
// Example code
// We cannot change this function
function thirdPartyModule() {
setTimeout(() =>
new Promise(() =>
{ throw null }))
}
main()