nextjs - 💡(How to fix) Fix [Turbopack] Intermittent structural hydration mismatch in Server Components (dev mode only) [2 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#90621Fetched 2026-04-08 00:19:46
View on GitHub
Comments
2
Participants
3
Timeline
6
Reactions
0
Author
Timeline (top)
commented ×2labeled ×2closed ×1locked ×1

Error Message

  1. Reload the page several times — the hydration error appears intermittently After several reloads, an intermittent hydration error appears:
  • The error is structural (element type mismatch), not a text content mismatch
  • The error is intermittent — it does not occur on every reload No hydration error. Server Components should not have hydration mismatches since they only render on the server. pnpm build && pnpm start (production mode) does not reproduce this error. The issue is specific to Turbopack dev mode.
  • #74357 — Similar Turbopack-only hydration error with simple components (closed/locked)
  • #85370 — Turbopack hydration error / double render with dynamic imports
  • #75830 — Turbopack-only hydration error with Chakra UI

Root Cause

Hydration failed because the server rendered HTML didn't match the client.

Fix Action

Workaround

pnpm build && pnpm start (production mode) does not reproduce this error. The issue is specific to Turbopack dev mode.

Code Example

// VideoCard.tsx (Server Component — no "use client")
export const VideoCard = ({ videoId, title, channelTitle }: Props) => {
    return (
        <div className="group rounded-lg">
            <a href={`https://www.youtube.com/watch?v=${videoId}`} target="_blank" rel="noopener noreferrer" className="block">
                <div className="relative aspect-video">
                    <img src={`https://i.ytimg.com/vi/${videoId}/sddefault.jpg`} alt={title} loading="lazy" />
                </div>
            </a>
            <div className="p-4">
                <a href={`https://www.youtube.com/watch?v=${videoId}`} target="_blank" rel="noopener noreferrer">
                    <h3>{title}</h3>
                </a>
                <p>{channelTitle}</p>
            </div>
        </div>
    );
};

---

Hydration failed because the server rendered HTML didn't match the client.

  <VideoCard>
    <div className="group roun...">
      <a>
+     <div className="p-4">
-     <a
-       href="https://www.youtube.com/watch?v=..."
-       target="_blank"
-       rel="noopener noreferrer"
-     >

---

Operating System:
  Platform: darwin (macOS 26.2)
  Arch: arm64
Binaries:
  Node: 22.16.0
  npm: 10.9.2
  pnpm: 10.26.1
Relevant Packages:
  next: 16.1.1
  react: 19.2.0
  react-dom: 19.2.0
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

No minimal reproduction repo yet — will create one if needed.

To Reproduce

  1. Create a Server Component that renders a list of card components (also Server Components) with the following structure:
// VideoCard.tsx (Server Component — no "use client")
export const VideoCard = ({ videoId, title, channelTitle }: Props) => {
    return (
        <div className="group rounded-lg">
            <a href={`https://www.youtube.com/watch?v=${videoId}`} target="_blank" rel="noopener noreferrer" className="block">
                <div className="relative aspect-video">
                    <img src={`https://i.ytimg.com/vi/${videoId}/sddefault.jpg`} alt={title} loading="lazy" />
                </div>
            </a>
            <div className="p-4">
                <a href={`https://www.youtube.com/watch?v=${videoId}`} target="_blank" rel="noopener noreferrer">
                    <h3>{title}</h3>
                </a>
                <p>{channelTitle}</p>
            </div>
        </div>
    );
};
  1. Render ~10 of these cards inside a horizontally scrollable container (also a Server Component)
  2. Run next dev (Turbopack enabled by default in Next.js 16)
  3. Reload the page several times — the hydration error appears intermittently

Current vs. Expected behavior

Current behavior:

After several reloads, an intermittent hydration error appears:

Hydration failed because the server rendered HTML didn't match the client.

  <VideoCard>
    <div className="group roun...">
      <a>
+     <div className="p-4">
-     <a
-       href="https://www.youtube.com/watch?v=..."
-       target="_blank"
-       rel="noopener noreferrer"
-     >

The server-rendered DOM has <div className="p-4"> (the info section) as the second child, but React expects <a> (the title link) at that position — as if the <div> wrapper was dropped from the RSC payload.

Key observations:

  • The affected component is a pure Server Component (no "use client", no hooks, no browser APIs)
  • All parent components are also Server Components
  • The error is structural (element type mismatch), not a text content mismatch
  • The error is intermittent — it does not occur on every reload
  • Tested in incognito window — same result (not caused by browser extensions)

Expected behavior:

No hydration error. Server Components should not have hydration mismatches since they only render on the server.

Workaround

pnpm build && pnpm start (production mode) does not reproduce this error. The issue is specific to Turbopack dev mode.

Provide environment information

Operating System:
  Platform: darwin (macOS 26.2)
  Arch: arm64
Binaries:
  Node: 22.16.0
  npm: 10.9.2
  pnpm: 10.26.1
Relevant Packages:
  next: 16.1.1
  react: 19.2.0
  react-dom: 19.2.0

Which area(s) are affected? (Select all that apply)

Turbopack

Which stage(s) are affected? (Select all that apply)

next dev (local)

Additional context

Related issues:

  • #74357 — Similar Turbopack-only hydration error with simple components (closed/locked)
  • #85370 — Turbopack hydration error / double render with dynamic imports
  • #75830 — Turbopack-only hydration error with Chakra UI

extent analysis

Fix Plan

1. Disable Turbopack Dev Mode

Turbopack dev mode is known to cause hydration errors in certain scenarios. Try disabling it by running next dev --no-turbo instead of next dev.

2. Update Next.js to the Latest Version

Next.js 16.1.1 is a relatively old version. Update to the latest version using npm install next@latest or pnpm install next@latest.

3. Use use client in Server Components

Even though the component is a pure Server Component, using use client can help Next.js optimize the RSC payload and prevent hydration errors.

// VideoCard.tsx (Server Component)
import { useClient } from 'next/client';

export const VideoCard = ({ videoId, title, channelTitle }: Props) => {
    const client = useClient();

    return (
        // ...
    );
};

4. Use getStaticProps or getServerSideProps to Pre-Render Components

Pre-rendering components using getStaticProps or getServerSideProps can help prevent hydration errors.

// VideoCard.tsx (Server Component)
import { getServerSideProps } from 'next';

export const getServerSideProps = async () => {
    // Pre-render the component
    return {
        props: {
            // ...
        },
    };
};

export const VideoCard = ({ videoId, title, channelTitle }: Props) => {
    return (
        // ...
    );
};

Verification

  1. Run next dev --no-turbo or next dev with the latest Next.js version.
  2. Reload the page several times to verify that the hydration error is resolved.
  3. Check the browser console for any errors.

Extra Tips

  • Make sure to update all dependencies, including react

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING