Route Validation

Reject Bad Params Before Rendering

Route Validation

definePageMeta validate lets a page refuse navigation when route params do not match expectations — return false and Nuxt shows the 404 page.

4 min read Level 3/5 #nuxt#validation
What you'll learn
  • Use definePageMeta validate to gate rendering
  • Return true to allow and false to reject
  • Handle the resulting 404 with a custom error page

Dynamic routes match anything — /users/42 and /users/banana both land on pages/users/[id].vue. Validation lets you reject obviously bad params before the page tries to render.

Numeric IDs Only

<!-- pages/users/[id].vue -->
<script setup lang="ts">
definePageMeta({
  validate: (route) => {
    return /^\d+$/.test(route.params.id as string)
  },
})

const { id } = useRoute().params
</script>

<template>
  <h1>User #{{ id }}</h1>
</template>

When the regex fails Nuxt aborts the navigation and renders the error page with a 404 status.

Async Validation

The validate function can be async — handy when a slug must exist in the database before the page renders.

definePageMeta({
  validate: async (route) => {
    const slug = route.params.slug as string
    const exists = await $fetch<boolean>(`/api/posts/${slug}/exists`)
    return exists
  },
})

Note: this server-side check fires on every navigation to the route, so keep the endpoint cheap.

Pairing With error.vue

Validation failures throw a createError({ statusCode: 404 }) under the hood. To customize the look, add a project-root error.vue:

<!-- error.vue -->
<script setup lang="ts">
const props = defineProps<{
  error: { statusCode: number; message: string }
}>()
</script>

<template>
  <h1>{{ props.error.statusCode }}</h1>
  <p>{{ props.error.message }}</p>
  <NuxtLink to="/">Go home</NuxtLink>
</template>

We will return to error pages in a dedicated lesson. Next up: nesting routes for shared layouts within a section.

Nested Routes →