Web Developer

|

Stockholm, Sweden

Delivering scalable solutions for
startups, enterprises, and agencies.

Hydration failed

Next.js Hydration Mismatch: Three Common Causes

The dreaded "initial UI does not match what was rendered on the server" error occurs when client-side React differs from server-rendered HTML. Here are the most likely culprits.

Issue #1: Invalid HTML structure

Incorrect HTML nesting breaks hydration because browsers automatically fix invalid markup, creating mismatches between server and client.

Common mistakes:

  • <div> inside <p> tags
  • Incorrect <ul> or <ol> usage
  • Heading tags nested within <p> elements
  • Interactive elements inside other interactive elements
Example: <p><div>Content</div></p> - The browser moves the div outside the p tag, but your React code expects it inside.

Issue #2: Browser extensions interfering

Extensions modify DOM content after the page loads, creating differences from the server-rendered version.

What happens:

  • Extensions inject additional attributes or elements
  • Ad blockers modify image or script tags
  • Accessibility extensions add extra markup
  • Translation extensions alter text content
An extension that adds data-extension-id to all images will cause hydration errors because this attribute wasn't present during server rendering.

Issue #3: Browser-specific code in components

Components using browser-only objects like window, document, or localStorage during render cause server/client mismatches.

The problem:

  • Server-side rendering can't access browser APIs
  • Component renders differently (or crashes) on server vs client
  • Conditional rendering based on browser features breaks hydration
A component checking window.innerWidth during render will show different content on server (no window object) versus client (actual width available).

Quick debugging tips

  • Use browser dev tools to compare server HTML with client DOM
  • Temporarily disable browser extensions to test
  • Wrap browser-specific code in useEffect hooks
  • Use suppressHydrationWarning={true} sparingly for debugging only
  • Check for invalid HTML with validators

The key is ensuring your component renders identically on both server and client until hydration completes.

Web Developer
Harry Yates 2025®