Fix: Invalid Character in Dynamic Route Parameter in Nuxt

Error message:
Invalid character in dynamic route parameter: {character}
navigation 2025-01-25

What Causes This Warning?

This warning appears when your dynamic route parameter (the part in square brackets) contains characters that aren’t valid for route parameter names.

The Problem

pages/
├── products/
│   ├── [product-id].vue     ❌ Hyphen not allowed
│   ├── [product.id].vue     ❌ Dot not allowed
│   ├── [product id].vue     ❌ Space not allowed
│   └── [product@id].vue     ❌ @ not allowed

The Fix

Use Valid Characters

pages/
├── products/
│   ├── [productId].vue      ✅ camelCase
│   ├── [product_id].vue     ✅ Underscore allowed
│   ├── [id].vue             ✅ Simple name
│   └── [productID].vue      ✅ PascalCase

Valid vs Invalid Characters

Valid

  • Letters: a-z, A-Z
  • Numbers: 0-9 (not at start)
  • Underscore: _

Invalid

  • Hyphen: -
  • Dot: .
  • Space:
  • Special characters: @, #, $, etc.

Examples

Product Routes

pages/
├── products/
│   ├── [id].vue             ✅ /products/123
│   ├── [productId].vue      ✅ /products/abc123
│   └── [slug].vue           ✅ /products/blue-widget

User Routes

pages/
├── users/
│   ├── [userId].vue         ✅ /users/123
│   └── [username].vue       ✅ /users/john_doe

Multi-Segment Catch-All

pages/
├── [...slug].vue            ✅ Catches all remaining segments
├── [...path].vue            ✅ Alternative name
└── docs/
    └── [...slug].vue        ✅ /docs/getting-started/installation

Accessing Route Parameters

<!-- pages/products/[productId].vue -->
<script setup>
const route = useRoute()

// Access the parameter
const productId = route.params.productId

// With TypeScript
const productId = route.params.productId as string
</script>

<template>
  <h1>Product: {{ productId }}</h1>
</template>

Multiple Parameters

pages/
├── [category]/
│   └── [productId].vue      ✅ /electronics/123
<!-- pages/[category]/[productId].vue -->
<script setup>
const route = useRoute()

const category = route.params.category     // 'electronics'
const productId = route.params.productId   // '123'
</script>

Optional Parameters

pages/
├── [[optionalId]].vue       ✅ / or /123
<!-- pages/[[optionalId]].vue -->
<script setup>
const route = useRoute()

// May or may not exist
const id = route.params.optionalId  // undefined or '123'
</script>

URL Formatting vs Parameter Names

The parameter NAME must be valid, but the actual URL VALUE can contain any characters:

<!-- pages/products/[slug].vue -->
<script setup>
const route = useRoute()

// Parameter name: slug (valid)
// URL value: 'blue-widget-2024' (can have hyphens)
const slug = route.params.slug  // 'blue-widget-2024'
</script>
URL: /products/blue-widget-2024

pages/products/[slug].vue

route.params.slug = 'blue-widget-2024'

Migration from Invalid Names

Before (Invalid)

pages/
└── products/
    └── [product-id].vue  ❌

After (Valid)

pages/
└── products/
    └── [productId].vue   ✅

Update code references:

<script setup>
const route = useRoute()

// Before
// const id = route.params['product-id']

// After
const id = route.params.productId
</script>

TypeScript Route Typing

// types/router.d.ts
declare module 'vue-router' {
  interface RouteParams {
    productId?: string
    categorySlug?: string
    userId?: string
  }
}

Quick Reference

File NameValid?URL Example
[id].vue/123
[productId].vue/abc123
[product_id].vue/abc_123
[product-id].vue-
[product.id].vue-
[...slug].vue/a/b/c

Quick Checklist

  • Parameter names use only letters, numbers, underscores
  • No hyphens in parameter names (use camelCase)
  • No dots or special characters
  • Numbers don’t start the parameter name
  • Update code when renaming parameters
  • Remember: URL values CAN have special characters