Next.jsReact

Hydration failed: server HTML didn't match the client

Hydration failed because the server rendered HTML didn't match the client.

In short: The first render on the server and the first render in the browser produced different HTML.

Why it happens

React renders the page on the server, then the browser renders it again and expects identical output. Anything that differs between the two runs breaks that: reading Date.now(), Math.random(), window, or localStorage during render; locale-dependent date formatting; invalid nesting like a <div> inside a <p>; or a browser extension that injects attributes into the page.

How to fix it

  1. Read the diff React prints in the browser console. It shows the exact element that differs.
  2. Move browser-only values (time, random IDs, localStorage, window.innerWidth) into useEffect so they're read after the first paint, or render a placeholder first.
  3. Fix invalid HTML nesting: no <div> inside <p>, no <a> inside <a>, no <tr> directly in <table> without <tbody>.
  4. For a value that legitimately differs (like a timestamp), add suppressHydrationWarning on that one element only.
  5. Test in a private window with extensions off. Some extensions (password managers, Grammarly) add attributes that trigger this warning.

Example

const [now, setNow] = useState<string | null>(null);
useEffect(() => { setNow(new Date().toLocaleTimeString()); }, []);
return <span>{now ?? '…'}</span>;
Don't: Don't wrap the whole app in a client-only dynamic import just to hide the warning. That throws away server rendering and SEO.

Copy-paste fix prompt

Paste into Cursor, Claude Code, Codex, Lovable, Bolt, Replit or v0
I'm getting this error in my app:

Hydration failed because the server rendered HTML didn't match the client.

[Paste the full error, stack trace, and the file it points to here]

Likely cause: The first render on the server and the first render in the browser produced different HTML.

Task: Find every value read during render that can differ between server and browser (dates, random values, window/localStorage, locale formatting) and any invalid HTML nesting in the component named in the error. Move browser-only values into useEffect. Change only those lines.

Rules:
- First explain the root cause in 2 sentences and list the files you'll change.
- Make the smallest change that fixes it. Don't refactor unrelated code.
- Don't disable security or checks (RLS, auth, signature verification, type checking, CORS allow-all) to make the error disappear.
- Never print or hard-code secret keys.
- Finish by telling me exactly how to verify the fix.

Common with: Cursor, v0, Bolt, Lovable. Last reviewed 2026-11-13.

Related fixes

← All fixes · Still stuck? Use the diagnose-first prompt