Fix: Invalid Layout Selected in Nuxt

Error message:
Invalid layout `{layout}` selected.
layouts 2025-01-25

What Causes This Error?

This warning appears when you reference a layout in your page that doesn’t exist in the layouts/ directory.

Common Causes and Fixes

Cause 1: Layout File Doesn’t Exist

// In your page
definePageMeta({
  layout: 'admin'  // But layouts/admin.vue doesn't exist!
})

Fix: Create the layout file:

<!-- layouts/admin.vue -->
<template>
  <div>
    <AdminSidebar />
    <main>
      <slot />
    </main>
  </div>
</template>

Cause 2: Typo in Layout Name

// ❌ Wrong - typo
definePageMeta({
  layout: 'defualt'  // Should be 'default'
})

// ✅ Correct
definePageMeta({
  layout: 'default'
})

Cause 3: Case Sensitivity

Layout names are derived from filenames and are case-sensitive:

// If your file is: layouts/AdminPanel.vue

// ❌ Wrong
definePageMeta({
  layout: 'adminpanel'
})

// ✅ Correct
definePageMeta({
  layout: 'AdminPanel'
})

Cause 4: Wrong Directory

Layouts must be in the layouts/ directory at the project root:

// ❌ Wrong locations
components/layouts/default.vue
pages/layouts/default.vue

// ✅ Correct location
layouts/default.vue

Cause 5: Dynamic Layout with Invalid Value

// ❌ Wrong - layout might be undefined or invalid
const layout = computed(() => user.value?.role)
definePageMeta({
  layout: layout  // Could be undefined!
})

// ✅ Correct - provide fallback
definePageMeta({
  layout: computed(() => user.value?.isAdmin ? 'admin' : 'default')
})

Creating Layouts

Basic Layout

<!-- layouts/default.vue -->
<template>
  <div>
    <Header />
    <slot />
    <Footer />
  </div>
</template>

Custom Layout

<!-- layouts/blog.vue -->
<template>
  <div class="blog-layout">
    <BlogHeader />
    <aside>
      <BlogSidebar />
    </aside>
    <main>
      <slot />
    </main>
  </div>
</template>

Using Layouts

Static Layout Assignment

// pages/admin/index.vue
definePageMeta({
  layout: 'admin'
})

Dynamic Layout

<script setup>
const route = useRoute()

definePageMeta({
  layout: false  // Disable layout initially
})

// Set layout dynamically
const layout = computed(() => {
  return route.meta.isAdmin ? 'admin' : 'default'
})
</script>

<template>
  <NuxtLayout :name="layout">
    <NuxtPage />
  </NuxtLayout>
</template>

Disabling Layout

definePageMeta({
  layout: false  // No layout for this page
})

Using setPageLayout

You can change layouts programmatically:

// Change layout at runtime
setPageLayout('admin')

Warning: Don’t call setPageLayout on the server or during hydration—it will cause errors.

Debugging

List available layouts:

# Check your layouts directory
ls -la layouts/

Or in your code:

// In nuxt.config.ts, add this to see registered layouts
export default defineNuxtConfig({
  hooks: {
    'pages:extend'(pages) {
      console.log('Layouts:', pages)
    }
  }
})

Layout Naming Convention

File NameLayout Name
default.vuedefault
admin.vueadmin
blog-post.vueblog-post
AdminPanel.vueAdminPanel

Quick Checklist

  • Layout file exists in layouts/ directory
  • File has .vue extension
  • Layout name matches filename exactly (case-sensitive)
  • No typos in layout name
  • Dynamic layout always resolves to valid value
  • Layout file has <slot /> for page content