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
- Read the diff React prints in the browser console. It shows the exact element that differs.
- Move browser-only values (time, random IDs,
localStorage,window.innerWidth) intouseEffectso they're read after the first paint, or render a placeholder first. - Fix invalid HTML nesting: no
<div>inside<p>, no<a>inside<a>, no<tr>directly in<table>without<tbody>. - For a value that legitimately differs (like a timestamp), add
suppressHydrationWarningon that one element only. - 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>;
Copy-paste fix prompt
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.