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.
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 →