Claude
Skills
Sign in
Back

debug:nuxtjs

Included with Lifetime
$97 forever

Debug Nuxt.js issues systematically. Use when encountering SSR errors, Nitro server issues, hydration mismatches like "Hydration text/node mismatch", composable problems with useFetch or useAsyncData, plugin initialization failures, module conflicts, auto-import issues, or Vue-specific runtime errors in a Nuxt context.

Web Dev

What this skill does


# 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:**
```typescript
// 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:**
1. Check browser console for specific mismatch details
2. Look for `window`, `document`, `localStorage` usage outside `onMounted` or `process.client`
3. Check for random values, dates, or user-specific data rendered during SSR
4. Use Vue DevTools to inspect component tree

### 2. useFetch/useAsyncData Errors

**Common Issues:**

```typescript
// 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:**
```typescript
// 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:**
```typescript
// 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]
})
```

### 3. Nitro Server Errors

**500 Internal Server Errors:**
```typescript
// 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:**
```typescript
// 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
})
```

### 4. Plugin Initialization Issues

```typescript
// 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
```

### 5. Module Conflicts

**Diagnosing Module Issues:**
```typescript
// 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:**
```bash
# 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)

```typescript
// 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

### 2. Sourcemaps Configuration

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

### 3. VS Code Debugging

Create `.vscode/launch.json`:
```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}"
    }
  ]
}
```

### 4. Node Inspector (Server-Side)

```bash
# Start with debugger
nuxi dev --inspect

# Or with specific host for Docker
nuxi dev --inspect=0.0.0.0
```

### 5. Console Logging (Server vs Client)

```typescript
// 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')
}
```

### 6. Vue DevTools

```bash
# 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:

```typescript
// 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

```vue
<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

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

watch([data, error, pending], ([d, e, p])

Related in Web Dev