Fix: Missing Required Param in Vue Router (Nuxt)

Error message:
Missing required param \"{param}\" when navigating to route: {route}
navigation 2025-01-25

What Causes This Error?

This error occurs when you try to navigate to a route that has required parameters, but you don’t provide all of them.

The Problem

<script setup>
// Route: /products/[id]
// ❌ Missing required 'id' parameter
navigateTo({ name: 'products-id' })

// ❌ Empty parameter
navigateTo({ name: 'products-id', params: { id: '' } })

// ❌ Undefined parameter
const productId = undefined
navigateTo(`/products/${productId}`)  // /products/undefined
</script>

The Fix

Provide Required Parameters

<script setup>
// ✅ Correct - provide the parameter
navigateTo({ name: 'products-id', params: { id: '123' } })

// ✅ Or use path directly
navigateTo('/products/123')

// ✅ With validation
const productId = ref('123')
if (productId.value) {
  navigateTo({ name: 'products-id', params: { id: productId.value } })
}
</script>

Common Scenarios

Dynamic Route Parameters

pages/
├── products/
│   └── [id].vue           → /products/:id (id is required)
├── blog/
│   └── [slug].vue         → /blog/:slug (slug is required)
└── users/
    └── [userId]/
        └── posts/
            └── [postId].vue → /users/:userId/posts/:postId (both required)
<script setup>
// Single parameter
navigateTo({ name: 'products-id', params: { id: '123' } })

// Multiple parameters
navigateTo({
  name: 'users-userId-posts-postId',
  params: {
    userId: 'user-1',
    postId: 'post-42'
  }
})
</script>
<template>
  <!-- ✅ Correct -->
  <NuxtLink :to="{ name: 'products-id', params: { id: product.id } }">
    {{ product.name }}
  </NuxtLink>

  <!-- ✅ Path interpolation -->
  <NuxtLink :to="`/products/${product.id}`">
    {{ product.name }}
  </NuxtLink>

  <!-- ❌ Wrong - missing param -->
  <NuxtLink :to="{ name: 'products-id' }">
    View Product
  </NuxtLink>
</template>

Handling Optional Parameters

Optional Catch-All

pages/
└── docs/
    └── [[...slug]].vue    → /docs or /docs/any/path
<script setup>
// This works without params (optional)
navigateTo({ name: 'docs' })
navigateTo({ name: 'docs', params: { slug: ['getting-started'] } })
</script>

Conditional Navigation

<script setup>
function viewProduct(id?: string) {
  if (!id) {
    // Handle missing ID
    console.error('Product ID required')
    return
  }

  navigateTo({
    name: 'products-id',
    params: { id }
  })
}
</script>

Debugging Route Names

<script setup>
// Find the correct route name
const router = useRouter()

onMounted(() => {
  // List all routes
  router.getRoutes().forEach(route => {
    console.log({
      name: route.name,
      path: route.path,
      params: route.path.match(/:\w+/g)  // Extract param names
    })
  })
})
</script>

TypeScript Type Safety

<script setup lang="ts">
// Define route params type
interface ProductParams {
  id: string
}

// Type-safe navigation
function goToProduct(params: ProductParams) {
  navigateTo({
    name: 'products-id',
    params
  })
}

// Usage
goToProduct({ id: '123' })  // ✅ TypeScript ensures id is provided
</script>

Common Mistakes

Using Wrong Route Name

<script setup>
// Route: pages/products/[id].vue
// Nuxt generates name: 'products-id'

// ❌ Wrong name format
navigateTo({ name: 'product', params: { id: '123' } })
navigateTo({ name: 'products/:id', params: { id: '123' } })

// ✅ Correct name
navigateTo({ name: 'products-id', params: { id: '123' } })
</script>

Forgetting Nested Parameters

pages/
└── users/
    └── [userId]/
        └── posts/
            └── [postId].vue
<script setup>
// ❌ Missing userId
navigateTo({
  name: 'users-userId-posts-postId',
  params: { postId: '42' }  // Missing userId!
})

// ✅ Provide both
navigateTo({
  name: 'users-userId-posts-postId',
  params: {
    userId: 'user-1',
    postId: '42'
  }
})
</script>

Fallback Handling

<script setup>
function safeNavigate(id: string | undefined) {
  if (!id) {
    // Redirect to list instead
    return navigateTo('/products')
  }

  return navigateTo({
    name: 'products-id',
    params: { id }
  })
}
</script>

Quick Checklist

  • All required route params are provided
  • Params are not empty strings or undefined
  • Using correct route name (check with router.getRoutes())
  • Nested routes have all parent params
  • Use optional params [[...slug]] if param isn’t always needed
  • Validate params before navigation