DevFixes
Next.jsIntermediateHigh severity

Hydration failed because the server rendered HTML did not match

The first client render produced different markup from the HTML generated on the server.

10-25 min Popularity 94/100 Verified 2026-07-21
Debug with AI

What does this error mean?

React expected to attach event handlers to server-rendered HTML, but the client calculated different content during its first render.

Why does this happen?

  • Using `Date.now()`, `Math.random()`, or locale-dependent formatting during render.
  • Reading browser-only APIs before the component mounts.
  • Invalid HTML nesting.
  • Data changed between server rendering and hydration.
  • A browser extension modified the document.

AI explanation

Plain-English analysis

Next.js rendered the component once on the server and React rendered it again in the browser. Hydration requires those two snapshots to agree. Any value that changes by time, environment, or browser state can make the snapshots diverge.

Quick fix

Terminal
Move browser-only values into useEffect.
Render deterministic placeholder content on the server.
Expected output: The initial server and client markup match, and the warning disappears.

Step-by-step fix

1Make the initial render deterministicPass server-generated values as props or defer volatile values until after mount.83%
2Move browser-only logic into a client effectAccess localStorage, window, or navigator after the component mounts.66%
3Correct invalid HTML nestingInspect the rendered DOM and ensure interactive elements and paragraphs are nested legally.38%

Alternative solutions

App Router

Add `"use client"` only to the smallest interactive component.

Client components are still server-pre-rendered unless dynamically disabled.

Dynamic import

dynamic(() => import("./BrowserOnly"), { ssr: false })

Use this for genuinely browser-only widgets, not as the first fix for every mismatch.

Real example

Broken
tsx
export function Clock() {
  return <time>{new Date().toLocaleTimeString()}</time>;
}
Corrected
tsx
"use client";

import { useEffect, useState } from "react";

export function Clock() {
  const [time, setTime] = useState<string | null>(null);
  useEffect(() => setTime(new Date().toLocaleTimeString()), []);
  return <time>{time ?? "--:--"}</time>;
}

Frequently asked questions

Use it only for a small, intentionally different text node such as a timestamp. It suppresses the warning but does not repair a structural mismatch.

References