vue-router: Throw Error "NavigationDuplicated"

Version

3.1.1

Reproduction link

https://codesandbox.io/s/vue-template-i2d63

Steps to reproduce

Use $router.push to change the “page”. If you are using the same page, vue-router throw an Error.

What is expected?

Just nothing, or a warning.

What is actually happening?

An Error has been thrown.


  • To my point of view it’s not an error. On a previous version of ‘vue-router’ no error was threw: https://codesandbox.io/s/vue-template-qvrfr
  • <router-link> does not have the same behavior. There is no error even if you’re pushing the current page.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 15 (7 by maintainers)

Most upvoted comments

This is expected, it’s part of the new promise api: before, if no callbacks were supplied to router.push, errors were only sent to the global router error handler. Now, because they return a promise, if the error is not caught, you will see a warning in the console. But the error was always there because trying to navigate to same location as the current one will fail

The behavior with router-link is consistent with how it was working before, no errors are emitted (except globally), it’s catching the error by adding a noop callback:

router.push('/location', () => {})

However, the correct solution if you don’t care about errors is catching the error:

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

@posva Why does it throw a NavigationDuplicated error when updating params, though? For instance, the router page might be named “User” and have params: { id: userId }. If you call this.$router.push({ name: 'User', params: { id: selectedUserId }}) to change the user being rendered for the current page, should that really count as a NavigationDuplicated error? This is the way it is recommended to change the data for a page, so it seems odd that getting an error is expected behavior.

I can confirm this behavior using this.$router.replace(). Just replacing the query params will cause the NavigationDuplicated error.

E.g., replacing #/search?term=lorem&sort=relevance with #/search?term=lorem&sort=alphabetical via

 this.$router.replace({
  path: '/search',
  query: {
    term: 'lorem',
    sort: 'alphabetical'
  }
})

will cause the NavigationDuplicated error if not catching via

 this.$router.replace({
  path: '/search',
  query: {
    term: 'lorem',
    sort: 'alphabetical'
  }
}).catch(err => {})

It will correctly update the current URL regardless of catching the error or not though.

Is this.$router.replace() not intended to be used for this? I didn’t see any other function in the docs for just replacing the query params.

Is there a shorter way the prevent the console warning than router.push('/location').catch(err => {})? Is it possible to decorate the push method to handle errors with a noop function?

@posva Why does it throw a NavigationDuplicated error when updating params, though? For instance, the router page might be named “User” and have params: { id: userId }. If you call this.$router.push({ name: 'User', params: { id: selectedUserId }}) to change the user being rendered for the current page, should that really count as a NavigationDuplicated error? This is the way it is recommended to change the data for a page, so it seems odd that getting an error is expected behavior.

It’s fixed now, I will publish a version during the day

pushing a new URL (that is the same path as current page) but the search/hash makes the URL different, doesn’t work anymore.

@posva Why does it throw a NavigationDuplicated error when updating params, though? For instance, the router page might be named “User” and have params: { id: userId }. If you call this.$router.push({ name: 'User', params: { id: selectedUserId }}) to change the user being rendered for the current page, should that really count as a NavigationDuplicated error? This is the way it is recommended to change the data for a page, so it seems odd that getting an error is expected behavior.

I can confirm this behavior using this.$router.replace(). Just replacing the query params will cause the NavigationDuplicated error.

E.g., replacing #/search?term=lorem&sort=relevance with #/search?term=lorem&sort=alphabetical via

 this.$router.replace({
  path: '/search',
  query: {
    term: 'lorem',
    sort: 'alphabetical'
  }
})

will cause the NavigationDuplicated error if not catching via

 this.$router.replace({
  path: '/search',
  query: {
    term: 'lorem',
    sort: 'alphabetical'
  }
}).catch(err => {})

It will correctly update the current URL regardless of catching the error or not though.

Is this.$router.replace() not intended to be used for this? I didn’t see any other function in the docs for just replacing the query params.

Is this fixed?