debug:nuxtjs

Nuxt.js Debugging Guide

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "debug:nuxtjs" with this command: npx skills add snakeo/claude-debug-and-refactor-skills-plugin/snakeo-claude-debug-and-refactor-skills-plugin-debug-nuxtjs

Nuxt.js Debugging Guide

This guide provides a systematic approach to debugging Nuxt.js applications, covering SSR/SSG issues, Nitro server problems, hydration mismatches, composables, and more.

Common Error Patterns

  1. Hydration Mismatches

Hydration mismatches occur when the server-rendered HTML differs from what Vue expects on the client.

Symptoms:

  • Console warning: "Hydration text/node mismatch"

  • Content flickers or changes after page load

  • [Vue warn]: Hydration completed but contains mismatches

Common Causes:

// BAD: Using browser-only APIs during SSR const windowWidth = window.innerWidth // Errors on server

// GOOD: Guard with process.client or useNuxtApp() const windowWidth = ref(0) onMounted(() => { windowWidth.value = window.innerWidth })

// GOOD: Use ClientOnly component <ClientOnly> <BrowserOnlyComponent /> </ClientOnly>

// BAD: Date/time rendering inconsistency <span>{{ new Date().toLocaleString() }}</span> // Different on server vs client

// GOOD: Use consistent formatting or client-only <ClientOnly> <span>{{ formattedDate }}</span> <template #fallback>Loading...</template> </ClientOnly>

Debugging Steps:

  • Check browser console for specific mismatch details

  • Look for window , document , localStorage usage outside onMounted or process.client

  • Check for random values, dates, or user-specific data rendered during SSR

  • Use Vue DevTools to inspect component tree

  1. useFetch/useAsyncData Errors

Common Issues:

// ERROR: "useFetch is not defined" or composable called outside setup // BAD: Calling in regular function function fetchData() { const { data } = useFetch('/api/data') // Error! }

// GOOD: Call in setup or use $fetch in functions const { data, error, pending, refresh } = useFetch('/api/data')

// Or for functions: async function fetchData() { const data = await $fetch('/api/data') }

Key/Caching Issues:

// BAD: Same key returns cached data const { data: user1 } = useFetch('/api/user', { key: 'user' }) const { data: user2 } = useFetch('/api/user', { key: 'user' }) // Returns same cached data!

// GOOD: Use unique keys const { data: user1 } = useFetch('/api/user/1', { key: 'user-1' }) const { data: user2 } = useFetch('/api/user/2', { key: 'user-2' })

// Force refresh const { data, refresh } = useFetch('/api/data') await refresh() // Bypasses cache

Watch for Reactive Parameters:

// BAD: Non-reactive parameter won't trigger refetch const userId = '123' const { data } = useFetch(/api/user/${userId})

// GOOD: Use computed or getter for reactive URLs const userId = ref('123') const { data } = useFetch(() => /api/user/${userId.value})

// Or with watch const { data } = useFetch('/api/user', { query: { id: userId }, watch: [userId] })

  1. Nitro Server Errors

500 Internal Server Errors:

// Check server/api/ files for issues // server/api/example.ts

// BAD: Unhandled errors crash the endpoint export default defineEventHandler(async (event) => { const data = await fetchExternalAPI() // Unhandled rejection return data })

// GOOD: Proper error handling export default defineEventHandler(async (event) => { try { const data = await fetchExternalAPI() return data } catch (error) { throw createError({ statusCode: 500, statusMessage: 'Failed to fetch data', data: { originalError: error.message } }) } })

Reading Request Body:

// BAD: Wrong method to read body export default defineEventHandler(async (event) => { const body = event.body // undefined!

// GOOD: Use readBody const body = await readBody(event)

// For query params const query = getQuery(event)

// For route params const { id } = event.context.params })

  1. Plugin Initialization Issues

// plugins/my-plugin.ts

// BAD: Plugin errors break the entire app export default defineNuxtPlugin(() => { const api = new ExternalAPI() // May throw })

// GOOD: Error handling in plugins export default defineNuxtPlugin({ name: 'my-plugin', enforce: 'pre', // or 'post' async setup(nuxtApp) { try { const api = new ExternalAPI() return { provide: { api } } } catch (error) { console.error('Plugin initialization failed:', error) // Provide fallback or skip } } })

// Client-only plugin export default defineNuxtPlugin({ name: 'client-only-plugin', setup() { // This only runs on client } }) // Name file: plugins/my-plugin.client.ts

  1. Module Conflicts

Diagnosing Module Issues:

// nuxt.config.ts export default defineNuxtConfig({ modules: [ '@nuxtjs/tailwindcss', '@pinia/nuxt', // Module order can matter! ],

// Debug module loading debug: true, // Shows module loading in console })

Common Module Conflicts:

Clear module cache

rm -rf node_modules/.cache rm -rf .nuxt

Reinstall dependencies

rm -rf node_modules npm install

Debugging Tools

  1. Nuxt DevTools (Recommended)

// nuxt.config.ts export default defineNuxtConfig({ devtools: { enabled: true } })

Features:

  • Component inspector and tree

  • Pages and routing visualization

  • Composables state inspection

  • Server routes overview

  • Module dependencies

  • Payload inspection

  • Timeline for performance

Access: Press Shift + Alt + D or click floating icon in dev mode

  1. Sourcemaps Configuration

// nuxt.config.ts export default defineNuxtConfig({ sourcemap: { server: true, client: true } })

  1. VS Code Debugging

Create .vscode/launch.json :

{ "version": "0.2.0", "configurations": [ { "type": "chrome", "request": "launch", "name": "Debug Nuxt Client", "url": "http://localhost:3000", "webRoot": "${workspaceFolder}" }, { "type": "node", "request": "launch", "name": "Debug Nuxt Server", "program": "${workspaceFolder}/node_modules/nuxi/bin/nuxi.mjs", "args": ["dev"], "cwd": "${workspaceFolder}" } ] }

  1. Node Inspector (Server-Side)

Start with debugger

nuxi dev --inspect

Or with specific host for Docker

nuxi dev --inspect=0.0.0.0

  1. Console Logging (Server vs Client)

// Runs on both server and client console.log('Universal log')

// Server-only logging if (process.server) { console.log('Server-side only') }

// Client-only logging if (process.client) { console.log('Client-side only') }

// In composables const nuxtApp = useNuxtApp() if (nuxtApp.ssrContext) { console.log('Server-side render') }

  1. Vue DevTools

Install Vue DevTools browser extension

Or use standalone

npx @vue/devtools

The Four Phases of Nuxt Debugging

Phase 1: Identify the Context

Determine where the error occurs:

// Check execution context console.log('Server:', process.server) console.log('Client:', process.client) console.log('Dev:', process.dev) console.log('SSR:', !!useNuxtApp().ssrContext)

Questions to answer:

  • Does it happen during SSR, hydration, or client navigation?

  • Is it a build-time or runtime error?

  • Does it only happen on certain routes?

  • Is it reproducible in development AND production?

Phase 2: Isolate the Component

<template> <div> <!-- Wrap suspect components --> <NuxtErrorBoundary @error="logError"> <SuspectComponent /> <template #error="{ error }"> <p>Error: {{ error.message }}</p> </template> </NuxtErrorBoundary> </div> </template>

<script setup> function logError(error) { console.error('Caught error:', error) } </script>

Phase 3: Check Data Flow

// Debug useFetch/useAsyncData const { data, error, pending, status } = useFetch('/api/data')

watch([data, error, pending], ([d, e, p]) => { console.log('Data:', d) console.log('Error:', e) console.log('Pending:', p) })

// Check payload (what's sent from server to client) const nuxtApp = useNuxtApp() console.log('Payload:', nuxtApp.payload)

Phase 4: Verify Build and Config

Type check

nuxi typecheck

Analyze bundle

nuxi analyze

Clean build

rm -rf .nuxt .output node_modules/.cache nuxi build

Quick Reference Commands

Development

Start dev server

nuxi dev

Start with debugging

nuxi dev --inspect

Start on specific port

nuxi dev --port 3001

Start with HTTPS

nuxi dev --https

Building and Analysis

Production build

nuxi build

Generate static site

nuxi generate

Preview production build

nuxi preview

Analyze bundle size

nuxi analyze

Type checking

nuxi typecheck

Prepare Nuxt (generate types)

nuxi prepare

Maintenance

Clean Nuxt files

nuxi cleanup

Upgrade Nuxt

nuxi upgrade

Add module

nuxi module add @nuxtjs/tailwindcss

Create new component/page/etc

nuxi add component MyComponent nuxi add page about nuxi add composable useMyComposable nuxi add api hello

Error Handling Patterns

Global Error Handler

// plugins/error-handler.ts export default defineNuxtPlugin((nuxtApp) => { nuxtApp.vueApp.config.errorHandler = (error, instance, info) => { console.error('Vue Error:', error) console.error('Component:', instance) console.error('Info:', info) }

nuxtApp.hook('vue:error', (error, instance, info) => { console.error('Nuxt Vue Error Hook:', error) })

nuxtApp.hook('app:error', (error) => { console.error('App Error:', error) }) })

Custom Error Page

<!-- error.vue (in root, NOT in pages/) --> <template> <div class="error-page"> <h1>{{ error.statusCode }}</h1> <p>{{ error.message }}</p> <button @click="handleError">Go Home</button> </div> </template>

<script setup> const props = defineProps({ error: Object })

const handleError = () => clearError({ redirect: '/' }) </script>

Programmatic Error Handling

// Throw errors throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true // Triggers error page })

// Show error without navigation showError({ statusCode: 500, statusMessage: 'Something went wrong' })

// Clear error clearError({ redirect: '/' })

// Access current error const error = useError()

Error Boundary for Components

<template> <NuxtErrorBoundary> <RiskyComponent />

&#x3C;template #error="{ error, clearError }">
  &#x3C;div class="error-box">
    &#x3C;p>Component failed: {{ error.message }}&#x3C;/p>
    &#x3C;button @click="clearError">Retry&#x3C;/button>
  &#x3C;/div>
&#x3C;/template>

</NuxtErrorBoundary> </template>

SSR-Specific Debugging

Payload Issues

// Debug what's in the payload const nuxtApp = useNuxtApp() onMounted(() => { console.log('SSR Payload:', nuxtApp.payload) console.log('SSR Data:', nuxtApp.payload.data) console.log('SSR State:', nuxtApp.payload.state) })

Async Data Not Available

// Ensure data is awaited properly const { data } = await useFetch('/api/data')

// For lazy loading (doesn't block navigation) const { data, pending } = useLazyFetch('/api/data')

// Watch for data availability watch(data, (newData) => { if (newData) { console.log('Data loaded:', newData) } })

Server-Only Code Leaking to Client

// Use server utilities correctly // server/utils/db.ts - only available in server/

// For runtime config (secrets) // nuxt.config.ts export default defineNuxtConfig({ runtimeConfig: { apiSecret: '', // Server-only public: { apiBase: '' // Exposed to client } } })

// Usage const config = useRuntimeConfig() // config.apiSecret - only on server // config.public.apiBase - available everywhere

Performance Debugging

Identify Slow Components

// nuxt.config.ts export default defineNuxtConfig({ experimental: { componentIslands: true // For heavy components } })

<!-- Use islands for heavy server components --> <NuxtIsland name="HeavyChart" :props="{ data: chartData }" />

Lazy Loading

// Lazy load components const HeavyComponent = defineAsyncComponent(() => import('~/components/HeavyComponent.vue') )

// Or use Nuxt's auto-import with Lazy prefix <template> <LazyHeavyComponent v-if="showHeavy" /> </template>

Bundle Analysis

Generate bundle analysis

nuxi analyze

Check what's in your bundle

cat .output/public/_nuxt/builds/meta/*.json | jq

Common Gotchas

  1. Composables Must Be Called in Setup

// BAD function handleClick() { const route = useRoute() // Error! }

// GOOD const route = useRoute() function handleClick() { console.log(route.path) }

  1. Reactive Data in useFetch

// BAD: Non-reactive const id = '123' useFetch(/api/items/${id})

// GOOD: Reactive const id = ref('123') useFetch(() => /api/items/${id.value})

  1. Navigate vs Router

// Prefer navigateTo over useRouter for navigation await navigateTo('/dashboard') await navigateTo({ path: '/user', query: { id: 1 } })

// For programmatic redirects in server export default defineEventHandler((event) => { return sendRedirect(event, '/login', 302) })

  1. Middleware Execution Order

// Named middleware runs in alphabetical order // middleware/01.auth.global.ts runs before middleware/02.analytics.global.ts

// Route-specific middleware definePageMeta({ middleware: ['auth', 'premium'] // Runs in order })

  1. State Pollution in SSR

// BAD: Shared state between requests const globalState = reactive({})

// GOOD: Use useState for SSR-safe state const state = useState('key', () => ({}))

// Or Pinia with proper SSR setup const store = useMyStore()

Resources

  • Nuxt Documentation - Debugging

  • Nuxt DevTools

  • Nuxt Error Handling

  • Vue DevTools

  • Nuxt GitHub Discussions

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

refactor:flutter

No summary provided by upstream source.

Repository SourceNeeds Review
General

refactor:nestjs

No summary provided by upstream source.

Repository SourceNeeds Review
General

refactor:spring-boot

No summary provided by upstream source.

Repository SourceNeeds Review