What Causes This Error?
This error occurs when two or more routes are registered with the same name. Route names must be unique in Vue Router.
The Problem
pages/
├── products.vue → name: 'products'
└── products/
└── index.vue → name: 'products' ← Conflict!
Or manual route registration:
// nuxt.config.ts
hooks: {
'pages:extend'(pages) {
pages.push({ path: '/custom', name: 'home', file: '~/pages/custom.vue' })
// But 'home' might already exist from pages/index.vue
}
}
The Fix
Option 1: Remove Conflicting File
pages/
├── products/ # Keep folder structure
│ └── index.vue → /products
└── # Remove products.vue
Or:
pages/
├── products.vue # Keep single file
└── # Remove products/ folder
Option 2: Rename Route
// nuxt.config.ts
export default defineNuxtConfig({
hooks: {
'pages:extend'(pages) {
const customPage = pages.find(p => p.path === '/custom')
if (customPage) {
customPage.name = 'custom-page' // Unique name
}
}
}
})
Option 3: Override Existing Route
// nuxt.config.ts
export default defineNuxtConfig({
hooks: {
'pages:extend'(pages) {
// Remove existing route first
const index = pages.findIndex(p => p.name === 'products')
if (index !== -1) {
pages.splice(index, 1)
}
// Add new one
pages.push({
path: '/products',
name: 'products',
file: '~/pages/custom-products.vue'
})
}
}
})
Understanding Nuxt Route Names
Automatic Naming Convention
pages/
├── index.vue → name: 'index'
├── about.vue → name: 'about'
├── products/
│ ├── index.vue → name: 'products'
│ └── [id].vue → name: 'products-id'
└── blog/
└── [slug]/
└── index.vue → name: 'blog-slug'
File vs Folder Conflict
pages/
├── products.vue → name: 'products', path: '/products'
└── products/
└── index.vue → name: 'products', path: '/products'
↑ CONFLICT!
Resolution: Choose one approach:
- Use
products.vuefor simple page - Use
products/index.vueif you’ll have nested routes
Module Routes
// modules/my-module/index.ts
export default defineNuxtModule({
setup(options, nuxt) {
nuxt.hook('pages:extend', (pages) => {
// Check if route name already exists
const existingRoute = pages.find(p => p.name === 'my-route')
if (!existingRoute) {
pages.push({
path: '/my-route',
name: 'my-route',
file: resolve('./runtime/pages/MyPage.vue')
})
} else {
console.warn('Route "my-route" already exists')
}
})
}
})
Debugging Duplicate Routes
// nuxt.config.ts
export default defineNuxtConfig({
hooks: {
'pages:extend'(pages) {
// Find duplicates
const names = pages.map(p => p.name)
const duplicates = names.filter((name, index) =>
names.indexOf(name) !== index
)
if (duplicates.length > 0) {
console.warn('Duplicate route names:', [...new Set(duplicates)])
console.warn('Routes:', pages.map(p => ({
name: p.name,
path: p.path,
file: p.file
})))
}
}
}
})
Custom Route Names
Override automatic naming:
<!-- pages/products.vue -->
<script setup>
definePageMeta({
name: 'products-list' // Custom name instead of 'products'
})
</script>
Alias Routes
Use aliases instead of duplicate routes:
// nuxt.config.ts
export default defineNuxtConfig({
hooks: {
'pages:extend'(pages) {
const productsRoute = pages.find(p => p.path === '/products')
if (productsRoute) {
productsRoute.alias = ['/items', '/shop']
}
}
}
})
Or in page:
<!-- pages/products.vue -->
<script setup>
definePageMeta({
alias: ['/items', '/shop']
})
</script>
Layer Conflicts
When using Nuxt layers:
// nuxt.config.ts
export default defineNuxtConfig({
extends: ['./base-layer'],
hooks: {
'pages:extend'(pages) {
// Check for conflicts with layer routes
console.log('All routes:', pages.map(p => p.name))
}
}
})
Quick Checklist
- No
products.vueANDproducts/index.vuefor same route - Manual routes have unique names
- Module routes check for existing names before adding
- Use
definePageMeta({ name })for custom names - Use aliases instead of duplicate routes
- Check layer routes for conflicts