All skills
vuejs-ai avatar

/vue-debug-guides

@a5fc891 official
by Vue AIvuejs-ai/skills2.9k stars
167

Vue 3 debugging and error handling for runtime errors, warnings, async failures, and SSR/hydration issues. Use when diagnosing or fixing Vue issues.

Use this Skill: https://skilld.dev/gh/vuejs-ai/skills/vue-debug-guides

This session only. Nothing lands on disk.

referencessr-hydration-mismatch-causes.md

≈1.7k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Understand and Fix SSR Hydration Mismatches

Impact: HIGH - Hydration mismatches occur when the HTML rendered on the client differs from what the server rendered. Vue attempts to recover by discarding and re-rendering mismatched nodes, causing performance degradation, visual flickering, and potentially broken event handlers.

Understanding the common causes helps you prevent and debug these issues effectively.

Task Checklist

  • Validate HTML structure for proper nesting (no div in p, no nested a tags)
  • Move random value generation to onMounted or use seeded randoms
  • Format dates/times on client side only
  • Use data-allow-mismatch (Vue 3.5+) for intentional mismatches
  • Check for browser-modified HTML in dev tools

Cause 1: Invalid HTML Nesting

Browsers auto-correct invalid HTML, creating different DOM than Vue expects.

Incorrect:

<template>
  <!-- WRONG: <div> cannot be inside <p> -->
  <p>
    <div>This will break hydration</div>
  </p>

  <!-- WRONG: <a> cannot be inside <a> -->
  <a href="/parent">
    <a href="/child">Nested link</a>
  </a>

  <!-- WRONG: Block elements in inline elements -->
  <span>
    <div>Block in inline</div>
  </span>
</template>

Browser converts the first example to:

<p></p>
<div>This will break hydration</div>
<p></p>

Correct:

<template>
  <!-- CORRECT: Use appropriate nesting -->
  <div>
    <div>This works fine</div>
  </div>

  <!-- CORRECT: Single link with event handling -->
  <a href="/parent" @click="handleParentClick">
    <span @click.stop="handleChildClick">Nested action</span>
  </a>

  <!-- CORRECT: Block element wrapper -->
  <div>
    <div>Block in block</div>
  </div>
</template>

Cause 2: Random Values in Render

Server and client generate different random values.

Incorrect:

<template>
  <!-- WRONG: Different ID on server vs client -->
  <div :id="'field-' + Math.random()">
    Form field
  </div>

  <!-- WRONG: Random order differs -->
  <div v-for="item in shuffledItems" :key="item.id">
    {{ item.name }}
  </div>
</template>

<script setup>
import { computed } from 'vue'

const items = [/* ... */]

// WRONG: Random shuffle runs differently on server and client
const shuffledItems = computed(() =>
  [...items].sort(() => Math.random() - 0.5)
)
</script>

Correct - Client-Only Random:

<template>
  <div :id="fieldId">
    Form field
  </div>

  <div v-for="item in displayItems" :key="item.id">
    {{ item.name }}
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'

const items = [/* ... */]

// CORRECT: Start with deterministic value
const fieldId = ref('field-default')
const displayItems = ref(items) // Original order on server

onMounted(() => {
  // Randomize only on client
  fieldId.value = 'field-' + Math.random().toString(36).slice(2)
  displayItems.value = [...items].sort(() => Math.random() - 0.5)
})
</script>

Correct - Seeded Random:

// utils/seededRandom.js
export function createSeededRandom(seed) {
  return function() {
    seed = (seed * 9301 + 49297) % 233280
    return seed / 233280
  }
}

// Use same seed on server and client
const seed = 12345 // Could be based on user ID, page, etc.
const random = createSeededRandom(seed)

Cause 3: Timezone and Date Differences

Server may be in different timezone than client.

Incorrect:

<template>
  <!-- WRONG: Server time != client time -->
  <span>{{ new Date().toLocaleTimeString() }}</span>

  <!-- WRONG: Server formats dates in server's timezone -->
  <span>{{ formatDate(article.createdAt) }}</span>
</template>

<script setup>
function formatDate(date) {
  return new Date(date).toLocaleDateString()
}
</script>

Correct:

<template>
  <!-- CORRECT: Render placeholder, update on client -->
  <span>{{ displayTime || 'Loading...' }}</span>

  <!-- CORRECT: Use UTC or defer to client -->
  <span>{{ formattedDate }}</span>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'

const props = defineProps(['article'])
const displayTime = ref(null)
const isClient = ref(false)

onMounted(() => {
  displayTime.value = new Date().toLocaleTimeString()
  isClient.value = true
})

// CORRECT: Server renders UTC, client converts to local
const formattedDate = computed(() => {
  if (!props.article?.createdAt) return ''

  if (isClient.value) {
    // Client: user's local timezone
    return new Date(props.article.createdAt).toLocaleDateString()
  } else {
    // Server: consistent UTC format
    return new Date(props.article.createdAt).toISOString().split('T')[0]
  }
})
</script>

Cause 4: Browser Extensions and Modifications

Browser extensions can inject content into the DOM.

Mitigation:

<template>
  <!-- Use data-allow-mismatch for areas extensions might modify -->
  <head data-allow-mismatch>
    <title>{{ pageTitle }}</title>
  </head>
</template>

Vue 3.5+ Suppressing Intentional Mismatches

<template>
  <!-- Suppress specific mismatch types -->
  <div data-allow-mismatch="text">
    {{ clientOnlyText }}
  </div>

  <!-- Suppress all mismatches for this element -->
  <div data-allow-mismatch>
    <ComplexClientComponent />
  </div>
</template>

Valid data-allow-mismatch values:

  • text - Text content mismatches
  • children - Child element mismatches
  • class - Class attribute mismatches
  • style - Style attribute mismatches
  • attribute - Other attribute mismatches
  • (no value) - All mismatches

Debugging Hydration Mismatches

// Enable detailed hydration mismatch warnings in development
// vite.config.js
export default {
  define: {
    __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: true
  }
}
<script setup>
import { onMounted } from 'vue'

// Debug: Compare server HTML with client expectation
onMounted(() => {
  const serverHTML = document.getElementById('app').innerHTML
  console.log('Server rendered:', serverHTML)
})
</script>

Common Error Messages

Error Likely Cause
"Hydration text content mismatch" Different text on server/client (dates, random)
"Hydration children mismatch" Invalid HTML nesting, conditional rendering
"Hydration attribute mismatch" Dynamic attributes with different values
"Hydration node mismatch" Completely different elements rendered

Reference

Source: SKILL.md on GitHub

1 warning17d5 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    This skill is a comprehensive collection of educational debugging guides and best practices for Vue 3 developers. It contains no executable code or malicious instructions and focuses solely on diagnosing common runtime errors and performance issues.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • Runlayer7mo

    140/140 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at a5fc891. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 8 months ago

README badge

README badge for vuejs-ai/skills/vue-debug-guides

Guides for diagnosing Vue 3 runtime errors, reactivity bugs, component lifecycle issues, and SSR hydration problems. Covers reactivity traps (refs, computed, watchers), component mechanics (props, emits, slots), templates (v-if, v-for, refs), forms (v-model), and composition API gotchas.

Generated from the current SKILL.md.

Does this cover Vue 2 or only Vue 3?
This skill is for Vue 3 only. It addresses Vue 3-specific debugging patterns like reactivity proxies, script setup, and defineEmits/defineProps.
Does this skill help with performance optimization?
No. This skill focuses on runtime errors, warnings, and behavioral bugs. For development best practices and optimization, use the separate `vue-best-practices` skill.
What kinds of issues does this cover?
Reactivity traps (refs, computed, watchers), component lifecycle bugs, template directives, form binding edge cases, SSR/hydration mismatches, slot scoping, and async-related failures.
Does this include debugging for Nuxt or other Vue frameworks?
No. This skill focuses on core Vue 3 runtime issues. Framework-specific bugs are outside its scope.

Generated from the current SKILL.md. These answers refresh after source changes.