-
-
Notifications
You must be signed in to change notification settings - Fork 5.1k
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
No stacktrace on NavigationDuplicated error uncaught in promise #2881
No stacktrace on NavigationDuplicated error uncaught in promise #2881
Comments
@rchl what navigator are you seeing this on? There are some limitations regarding error stacktraces that may lead to errors being uncomplete in browsers like IE9 |
I'm seeing this on every browser as it's not specific to a browser but to transpiled variant of the code. Instantiating such transpiled "class" is not gonna produce a stack trace as inheritance of |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
After many iterations I've created better testcase at https://jsfiddle.net/Lom7hxn5/ (also updated original comment). Notice that in your screenshot you have two chevrons to expand. The one you've expanded is not actually the error object itself but something else (I think promise rejection exception). The error itself doesn't have a stack trace. My new testcase just catches promise rejection and console.log's the error. That should also show stack trace but doesn't currently. Note: If using |
Also here is a version using esm version of VueRouter (in browsers that support ES modules): https://jsfiddle.net/L8wykjns/5/ You can see that logged error actually has stack trace in this one. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
I understand it may be a bit confusing to see the UncaughRejection error in the console, so let me summarize what it's all about: The error you see in the console is part of the new promise api: before, if no callbacks were supplied to This behavior doesn't happen with router.push('/location', () => {}) But if you are using router.push('/location').catch(err => {}) The last version makes more sense as the Promise api is likely to become the default and the callback version to become deprecated. This isn't a breaking change because the code still works the same it was before. The only exceptions are if you were doing one of these: return router.push('/location') // this is now returning the promise
await router.push('/location') // this explicitly awaits for the navigation to be finished However, If you want to handle this globally, you can replace Router's push/replace functions to silence the rejection and make the promise resolve with the error instead: import Router from 'vue-router'
const originalPush = Router.prototype.push
Router.prototype.push = function push(location, onResolve, onReject) {
if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
return originalPush.call(this, location).catch(err => err)
} I discourage from swallowing the errors like this because doing With the new navigation failures, you can replicate vue-router-next behavior: import Router from 'vue-router'
const originalPush = Router.prototype.push
Router.prototype.push = function push(location, onResolve, onReject) {
if (onResolve || onReject)
return originalPush.call(this, location, onResolve, onReject)
return originalPush.call(this, location).catch((err) => {
if (Router.isNavigationFailure(err)) {
// resolve err
return err
}
// rethrow error
return Promise.reject(err)
})
} This was reported already at #2872 and #2873. This issue is about improving the stack trace of the Rejection so if you could keep the conversation about that, it would help me a lot! I hope that this answer, being more detailed brings clarity to the topic. I've also been looking at how this impacts Nuxt with their core team so the error doesn't appear if it shouldn't. |
hey @posva thanks so much for the thorough breakdown. I think the confusion is coming into play regarding what you described when you said: "However, the failure was always there because trying to navigate to same location as the current one fails. It's now visible because of the promise being rejected but not caught." While I understand that the above is true, I don't think it was unreasonable for anyone to assume that the router's default behavior would be to handle the NavigationDuplicated usecase "out of the box"... I've been using vue-router for several years, and I thought this was just default functionality all along. I'm absolutely a fan of the promise API and see some immediate benefits, but I've had to rollback vue-router to a pre 3.1 version because I don't have a way of cleaning up the errors that are being thrown without adding Perhaps we can spin up a separate "feature request" issue for handling NavigationDuplicated out of the box? |
@posva It's not related to NavigationDuplicated but to stacktrace. on a |
I'm glad you could find it useful @shayneo !
I want to be clear about this: it wasn't handled out of the box before, the navigation failure was ignored. It was a behavior that could cause bugs (as explained in the comment) and we are now making it visible.
Yes, you do have a way to do it, I added a code snippet to override the function if the errors in the console are too noisy. You can also include a Having an option to silence that specific navigation failure doesn't seem like a good api choice imo, as it's a failure like others and I think people just got used to not having to handle it. It's achievable in user land with the snippet above though. It's something that could evolve in future major versions, but this behavior is consistent with the callback version of navigation functions. For it to evolve it will be necessary to redefine what a navigation success means (everything that isn't a success is a failure and makes the Promise rejection). Right now, navigation succeeds if the navigation resolves correctly to what we pass as the first argument (the target location). Any guard navigation aborting or redirecting, not navigating (same location) as well as errors, abort the navigation, making it reject. If you think this isn't the right way, it would help to discuss it in an RFC with pros/cons and other alternatives |
@frlinw Errors are being improved, there were no proper errors before so some rejections still need to be improved |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This RFC improves navigation failures and should address some of the problems people were facing regarding the uncaught promise rejections: vuejs/rfcs#150 |
…n error, see vuejs/vue-router#2881 (comment). It seems it's not supposed to throw the error if parameters are changed, so maybe a bug in vue-router?
* Package updates * Update for new output names * Update permissions editor to vue-cli 4.3.x * Update vue-cdr-access packages * Router push needs a catch block, as navigating to same route throws an error, see vuejs/vue-router#2881 (comment). It seems it's not supposed to throw the error if parameters are changed, so maybe a bug in vue-router? * * Update vue-cdr-access packages * Security fixes * Fix issue with js build not overwriting previous build * Update vue-test-utils and fix tests. There were breaking changes in 1.0.0-beta.30
…next(object) always reject, after vue-router v3.1.0.Also see vuejs/vue-router#2881 (comment)
This comment has been minimized.
This comment has been minimized.
I did not ignore it. I listened to the feedback and came up with vuejs/rfcs#150 which was well received. It addresses your concern too. And to answer your question, no, I don't think a duplicated navigation it's an error. Locking this thread as it's outdated after the RFC and comments like yours, which are negative and clearly a rant with sentences like Because I can give you a million cases and I have about a million of these buttons live in production, it's not something I need to deal with. |
Version
3.1.1
Reproduction link
https://jsfiddle.net/Lom7hxn5/
Steps to reproduce
$router.replace
or$router.push
twice with same pathWhat is expected?
Error object provides stacktrace (stack property)
What is actually happening?
No stack trace in the error object
When
NavigationDuplicated
error is thrown, there is no stack trace in the error itself so when error is reported through error reporting service likeSentry
, there is absolutely no context to go with the error and so it's hard to figure out where that error originated.Transpiled code for the
NavigationDuplicated
class looks like this:vue-router/dist/vue-router.common.js
Lines 1935 to 1946 in 5141def
which is problematic because instantiating such function won't create a stacktrace. It would work fine with non-transpiled code (although I'm not suggesting to not transpile it):
vue-router/src/history/errors.js
Line 1 in 44c63a9
One possible solution would be to manually set stack trace with:
but I'm not sure how that would be done if transpilation is done by webpack/babel...
There is also one extra bug in that code. The line that instantiates error passes a route object to the error:
vue-router/src/history/base.js
Line 125 in fc42d9c
but error doesn't do anything with it:
vue-router/src/history/errors.js
Line 2 in 44c63a9
Saving route properties on the error object would also help in deciphering source of the error.
The text was updated successfully, but these errors were encountered: