Skip to content

Next.js and React errorNext.js hydration error: the server HTML didn’t match the browser

The page loads, then the console or the Next.js error overlay says hydration failed, and parts of the page flicker or stop responding. React expected the browser’s first render to match the HTML the server sent, and something made them differ. Here’s what usually does it, in the Next.js docs’ own words, or hand it over at a fixed price.

Short answer

Find what renders differently on the server and in the browser. Most often it’s a browser-only value read during render (window, localStorage, the current time, a random number): move it into useEffect, so the first browser render matches the server. If that isn’t it, check for invalid HTML nesting, such as a <div> inside a <p> or a link inside a link, then test in a private window without extensions.

What makes the server and browser disagree, most common first

  1. 01

    Browser-only values read during render

    “During React hydration, useEffect is called. This means browser APIs like window are available to use without hydration mismatches.” Next.js, Text content does not match server-rendered HTML

    The server has no window, localStorage or user time zone, so code that checks whether window exists, reads localStorage.getItem() or calls new Date() in a component’s render gives the server one answer and the browser another. Render the same thing on both, then switch to the browser value after mount.

    const [isClient, setIsClient] = useState(false);
    useEffect(() => setIsClient(true), []);
    
    return <span>{isClient ? new Date().toLocaleTimeString() : ''}</span>;
  2. 02

    HTML nested in a way browsers don’t allow

    A <div> or a list inside a <p>, a <p> inside another <p>, a link inside a link or a button inside a button. Browsers can auto-correct invalid nesting while parsing, so the HTML no longer matches what React renders. The error often points at the element.

  3. 03

    A browser extension or iOS changed the page

    “iOS attempts to detect phone numbers, email addresses, and other data in text content and convert them into links, leading to hydration mismatches.” Next.js, Text content does not match server-rendered HTML

    Extensions that modify the page edit the HTML before React hydrates. If the error disappears in a private window with extensions off, it isn’t your code. On iPhone, Safari turns phone numbers, emails and addresses into links unless you turn that off with a format-detection meta tag.

    <meta name="format-detection" content="telephone=no, date=no, email=no, address=no" />
  4. 04

    A CDN or proxy rewrote the HTML

    If the error only appears on the live site, check whether your CDN or proxy minifies or injects anything into the HTML. The Next.js docs name a misconfigured Edge or CDN layer as a cause, with Cloudflare Auto Minify as the example. An incorrectly configured CSS-in-JS library is on the same list.

  5. 05

    Content that really is different, like a timestamp

    “This only works one level deep, and is intended to be an escape hatch. Don’t overuse it.” Next.js, Text content does not match server-rendered HTML

    When a value has to differ, such as a time rendered on the server, add suppressHydrationWarning to that one element. It covers that element only, one level deep, so it isn’t a fix for a whole component. For a component that can only work in the browser, load it with next/dynamic and ssr: false from a Client Component.

Checked against the vendor’s docs on : Next.js docs: Text content does not match server-rendered HTML; Next.js docs: Lazy loading (ssr: false); React reference: hydrateRoot.

Rather hand it over?

Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.

Related: Lovable app blank after publishing · Build fails on Netlify or Vercel · Vercel environment variables undefined

Questions

More on this error

Can I just ignore the warning if the page looks fine?

React’s docs say to treat mismatches as bugs and fix them. React doesn’t guarantee it will patch attribute differences, so the page can stay wrong. Fix the cause, and keep suppressHydrationWarning for single values like timestamps.

I added ssr: false and now I get a different error. Why?

next/dynamic with ssr: false only works inside a Client Component. Next.js shows an error if you use it in a Server Component. Add 'use client' to a small wrapper component and load the browser-only part from there.

It only happens for some users. How do I find it?

That points to the browser side: extensions, iOS link detection, or values like time zone and locale that differ by user. Ask for the browser and device, try a private window, and look for dates or numbers formatted in render.

Can you fix it for me?

If one bug is the whole problem, the App Fix Ticket covers it: a written diagnosis first, then the fix. If the app has more going on, the Launch Check is a written check of the whole app. Each issue found is rated critical, high, medium or low, with where it is and how it was confirmed. No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way.

A different error?

Describe it and get a written quote

Send the error and what you were doing. You get a written scope, a fixed price and a timeline; we reply by email, usually within one business day.