{"record":{"id":"5f600fa5ab80028b","repo":"Meituan-Dianping/mpvue","slug":"the-client-side-rendered-virtual-dom-tree-is-not-m","errorCode":null,"errorMessage":"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.","messagePattern":"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\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/core/vdom/patch.js","lineNumber":627,"sourceCode":"      const isRealElement = isDef(oldVnode.nodeType)\n      if (!isRealElement && sameVnode(oldVnode, vnode)) {\n        // patch existing root node\n        patchVnode(oldVnode, vnode, insertedVnodeQueue, removeOnly)\n      } else {\n        if (isRealElement) {\n          // mounting to a real element\n          // check if this is server-rendered content and if we can perform\n          // a successful hydration.\n          if (oldVnode.nodeType === 1 && oldVnode.hasAttribute(SSR_ATTR)) {\n            oldVnode.removeAttribute(SSR_ATTR)\n            hydrating = true\n          }\n          if (isTrue(hydrating)) {\n            if (hydrate(oldVnode, vnode, insertedVnodeQueue)) {\n              invokeInsertHook(vnode, insertedVnodeQueue, true)\n              return oldVnode\n            } else if (process.env.NODE_ENV !== 'production') {\n              warn(\n                'The client-side rendered virtual DOM tree is not matching ' +\n                'server-rendered content. This is likely caused by incorrect ' +\n                'HTML markup, for example nesting block-level elements inside ' +\n                '<p>, or missing <tbody>. Bailing hydration and performing ' +\n                'full client-side render.'\n              )\n            }\n          }\n          // either not server-rendered, or hydration failed.\n          // create an empty node and replace it\n          oldVnode = emptyNodeAt(oldVnode)\n        }\n        // replacing existing element\n        const oldElm = oldVnode.elm\n        const parentElm = nodeOps.parentNode(oldElm)\n        createElm(\n          vnode,\n          insertedVnodeQueue,","sourceCodeStart":609,"sourceCodeEnd":645,"githubUrl":"https://github.com/Meituan-Dianping/mpvue/blob/6c5d78ee04f58c6d782c456dfcf0fe63c0b7f89b/src/core/vdom/patch.js#L609-L645","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Make server and client render identical output: move non-deterministic values (time, random, window checks) into `mounted` or wrap in `<client-only>`","Fix invalid HTML nesting (no block elements inside `<p>`; include `<tbody>` in tables)","Diff the server HTML against the client render to find the first mismatch (Vue devtools or console inspection)","As a last resort accept the warning — Vue still renders correctly client-side, just without hydration benefits"],"exampleFix":"// before\n<p><div v-if=\"wide\">wide</div></p>\n// after\n<div><div v-if=\"wide\">wide</div></div>","handlingStrategy":"fallback","validationCode":"// pre-render sanity check for SSR determinism\nfunction assertDeterministicRender (renderFn) {\n  const a = renderFn(), b = renderFn()\n  if (JSON.stringify(a) !== JSON.stringify(b)) {\n    console.warn('render is non-deterministic — hydration will mismatch')\n  }\n}","typeGuard":null,"tryCatchPattern":"// hydration is not thrown, but you can detect the bail-out:\nmounted () {\n  this.$nextTick(() => {\n    if (this.$el.dataset && this.$el.dataset.serverRendered === undefined) {\n      console.warn('hydration bailed; full client render occurred')\n    }\n  })\n}","preventionTips":["Avoid Date.now(), Math.random(), and window checks in render/template","Wrap browser-only content in <client-only> or render after mounted","Keep server HTML valid (no block-in-<p>, always <tbody>)","Test SSR output vs client render in CI"],"tags":["ssr","hydration","vdom"],"backgroundTag":"hydration-mismatch","analyzedSha":"6c5d78ee04f58c6d782c456dfcf0fe63c0b7f89b","analyzedAt":"2026-09-02T05:17:40.946Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T11:17:12.671Z"}