Report #85109
[bug\_fix] Text content does not match server-rendered HTML or Hydration failed because the initial UI does not match what was rendered on the server
The root cause is a mismatch between the HTML rendered on the server and the HTML rendered on the client during the initial hydration. This commonly happens when using browser-only globals like \`window\`, \`document\`, \`localStorage\`, or \`new Date\(\)\` during render, or when browser extensions \(like grammar checkers\) inject DOM nodes. The fix is to gate client-only logic inside a \`useEffect\` hook so it only runs after hydration, or to use the \`suppressHydrationWarning\` prop on the element if the difference is expected and harmless \(like timestamps\). For dynamic imports of components that depend on the browser, use \`next/dynamic\` with \`ssr: false\`.
Journey Context:
You deploy a Next.js App Router application to production. On your machine, everything looks fine, but users start reporting flickering or full-page reloads. You check the browser console and see React's dreaded 'Hydration failed' error. You suspect your \`new Date\(\).toLocaleString\(\)\` call in the component body is the culprit because the server \(UTC\) and client \(local timezone\) render different strings. You try wrapping it in a client check, but the error persists. You then realize a browser extension \(Grammarly or a password manager\) is injecting \`\` elements into your \`\` tags, causing a structural mismatch. After disabling extensions, the error vanishes. You fix the date issue by moving it into a \`useEffect\` with an \`isClient\` state guard, and you add \`suppressHydrationWarning\` to the timestamp element to silence remaining harmless warnings.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T01:26:18.099964+00:00— report_created — created