Skip to content
Latchkey

Next.js "Hydration failed because the initial UI does not match"

React hydration requires the client's first render to match the server-rendered HTML exactly. When they diverge - because of Date.now(), window, random values, or invalid nesting - React throws a hydration error.

What this error means

The page logs Hydration failed because the initial UI does not match what was rendered on the server (or Text content does not match server-rendered HTML). It can fail strict CI checks and breaks interactivity on the affected subtree.

browser console / build check
Error: Hydration failed because the initial UI does not match what was
rendered on the server.
Warning: Text content did not match. Server: "12:00:00" Client: "12:00:01"
    at time
    at Clock (Clock.tsx:6:20)

Common causes

Non-deterministic render

Using Date.now(), Math.random(), or locale/timezone-dependent formatting produces different output on server and client, so the markup mismatches.

Browser-only APIs during render

Reading window, localStorage, or navigator during the initial render makes the client diverge from the server (where those are undefined).

Invalid HTML nesting

Markup the browser auto-corrects - a <div> inside a <p>, a <p> inside a <p> - makes the parsed client DOM differ from the server string.

How to fix it

Defer client-only values to after mount

Render a stable placeholder on the server, then set the dynamic value in an effect so it only runs on the client.

TSX
const [now, setNow] = useState<string | null>(null)
useEffect(() => { setNow(new Date().toLocaleTimeString()) }, [])
return <time>{now ?? ''}</time>

Fix invalid nesting and guard browser APIs

  1. Validate HTML nesting (no block elements inside <p>, no <div> inside inline elements).
  2. Never read window/localStorage during render; do it in an effect.
  3. For inherently client-only widgets, load them with next/dynamic and { ssr: false }.

How to prevent it

  • Keep the initial render deterministic and server-safe.
  • Move browser-API reads into effects, not render.
  • Validate HTML nesting so the parsed DOM matches the server string.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →