Hydration failed
The HTML the server sent didn’t match what React rendered first in the browser, so React threw that part away and rebuilt it on the client.
Also appears as
- Hydration failed because the server rendered text didn't match the client. As a result this tree will be regenerated on the client.
- A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up.
- Minified React error #418; visit https://react.dev/errors/418?args[]=HTML&args[]= for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
- Hydration failed because the initial UI does not match what was rendered on the server.
- Text content does not match server-rendered HTML.
- There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.
Prompt to fix it
My app shows "Hydration failed because the server rendered HTML didn't match the client." Find the component that renders differently on the server and in the browser. Check for window, localStorage, or matchMedia reads during render, Date.now(), new Date(), Math.random(), dates formatted in the visitor’s locale, and invalid HTML nesting such as a div inside a p. Move browser-only values into useEffect with a first render that matches the server, and use useId for generated IDs. Don’t hide it with suppressHydrationWarning or turn off server rendering for the page. Tell me which mismatch you found.
Paste into Layerwise or any AI coding tool.
What it means
With server rendering, as in Next.js, the server sends finished HTML so the page appears fast. React then runs the same components in the browser and attaches to that HTML instead of building it again. That step is called hydration, and it only works if the first browser render produces exactly the markup the server sent.
When the two differ, React discards the server HTML for that part of the page and renders it again in the browser. The page usually still works, but it flickers, loses the speed benefit of server rendering, and in production logs a short Minified React error #418. In development, the error shows a diff: lines marked + are what the browser rendered, and lines marked - are what the server sent.
A common AI-written fix causes this error: wrapping code in if (typeof window !== 'undefined') during render. The server takes one branch and the browser takes the other, so the HTML can never match. Browser-only values belong in useEffect, which runs after hydration.
Common causes
- A component reads
window,localStorage, or the screen size while rendering, so the server and the browser render different output. - The markup includes
new Date(),Date.now(),Math.random(), or a date formatted in the visitor’s locale or time zone. - The HTML nesting is invalid, such as a
<div>inside a<p>or a link inside a link, and the browser rearranges it before React hydrates. - A browser extension, such as a password manager, translator, or grammar checker, changes the page before React loads.
How to fix it
- Read the diff in the error overlay or console to find the element and the value that differ.
- Move reads of
window,localStorage, andmatchMediaintouseEffect, and render a neutral default until the effect runs. - Render times and random values after mount, or format dates with a fixed
timeZoneso both sides agree. UseuseId()for generated IDs. - Fix invalid nesting: no
<div>or<p>inside a<p>, no links inside links, and table rows inside a<tbody>. - Reload in a private window with extensions off. If the error disappears, an extension caused it and your code is fine.
Example fix
'use client';
import { useEffect, useState } from 'react';
export function LocalTime({ iso }: { iso: string }) {
// Empty on the server and on the first browser render, so both match.
const [text, setText] = useState('');
useEffect(() => {
setText(new Date(iso).toLocaleString());
}, [iso]);
return <time dateTime={iso}>{text}</time>;
}Related errors
All errorsReferenceError: window is not defined
Code that only works in a browser ran on the server, where there is no window, document, or localStorage.
You’re importing a component that needs useState
A Next.js Server Component used a browser-side React feature like useState, which only works in files marked as Client Components.
Too many re-renders
A component changes its own state while it renders, so React renders it again and again until it stops the loop.
Each child in a list should have a unique "key" prop
A list rendered with map gave its items no stable ID, so React can’t tell which item is which when the list changes.
Build with an agent that checks its work
The Layerwise agent clicks through the live preview and reads the console, so it catches errors before you do.