Meituan-Dianping/mpvue · error

The client-side rendered virtual DOM tree is not matching se

Error message

The client-side rendered virtual DOM tree is not matching server-rendered content. This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>. Bailing hydration and performing full client-side render.

What it means

During SSR hydration, the client-generated virtual DOM tree did not match the server-rendered HTML at the same position. Vue abandons hydration entirely and performs a full client-side re-render, which can cause a visible flash/reflow and lost server-render benefits.

Source

Thrown at src/core/vdom/patch.js:627

      const isRealElement = isDef(oldVnode.nodeType)
      if (!isRealElement && sameVnode(oldVnode, vnode)) {
        // patch existing root node
        patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly)
      } else {
        if (isRealElement) {
          // mounting to a real element
          // check if this is server-rendered content and if we can perform
          // a successful hydration.
          if (oldVnode.nodeType === 1 && oldVnode.hasAttribute(SSR_ATTR)) {
            oldVnode.removeAttribute(SSR_ATTR)
            hydrating = true
          }
          if (isTrue(hydrating)) {
            if (hydrate(oldVnode, vnode, insertedVnodeQueue)) {
              invokeInsertHook(vnode, insertedVnodeQueue, true)
              return oldVnode
            } else if (process.env.NODE_ENV !== 'production') {
              warn(
                'The client-side rendered virtual DOM tree is not matching ' +
                'server-rendered content. This is likely caused by incorrect ' +
                'HTML markup, for example nesting block-level elements inside ' +
                '<p>, or missing <tbody>. Bailing hydration and performing ' +
                'full client-side render.'
              )
            }
          }
          // either not server-rendered, or hydration failed.
          // create an empty node and replace it
          oldVnode = emptyNodeAt(oldVnode)
        }
        // replacing existing element
        const oldElm = oldVnode.elm
        const parentElm = nodeOps.parentNode(oldElm)
        createElm(
          vnode,
          insertedVnodeQueue,

View on GitHub (pinned to 6c5d78ee04)

Solutions

  1. Make server and client render identical output: move non-deterministic values (time, random, window checks) into `mounted` or wrap in `<client-only>`
  2. Fix invalid HTML nesting (no block elements inside `<p>`; include `<tbody>` in tables)
  3. Diff the server HTML against the client render to find the first mismatch (Vue devtools or console inspection)
  4. As a last resort accept the warning — Vue still renders correctly client-side, just without hydration benefits

Example fix

// before
<p><div v-if="wide">wide</div></p>
// after
<div><div v-if="wide">wide</div></div>
Defensive patterns

Strategy: fallback

Validate before calling

// pre-render sanity check for SSR determinism
function assertDeterministicRender (renderFn) {
  const a = renderFn(), b = renderFn()
  if (JSON.stringify(a) !== JSON.stringify(b)) {
    console.warn('render is non-deterministic — hydration will mismatch')
  }
}

Try / catch

// hydration is not thrown, but you can detect the bail-out:
mounted () {
  this.$nextTick(() => {
    if (this.$el.dataset && this.$el.dataset.serverRendered === undefined) {
      console.warn('hydration bailed; full client render occurred')
    }
  })
}

Prevention

When it happens

Trigger: Server and client render different markup: date/`Date.now()`/random values, browser-only conditionals (`typeof window !== 'undefined'`), invalid HTML nesting that the browser rewrites (block elements inside `<p>`, tables missing `<tbody>`), whitespace/attribute differences, different v-for lengths.

Common situations: Nuxt/SSR apps rendering timestamps or locale-dependent strings; browser auto-correcting malformed server HTML so the client's parsed tree differs; user-agent-dependent markup; mismatched component state hydrated incorrectly.

Related errors


AI-assisted analysis of Meituan-Dianping/mpvue@6c5d78ee04 (2026-09-02). Data as JSON: /api/errors/5f600fa5ab80028b. Report an issue: GitHub.