# Hydration Proof > Detect React hydration errors in CI: hydration-proof compares real server HTML with the hydrated DOM in Next.js, Remix and Astro, then explains the cause. Hydration Proof documents two npm packages that find, explain and prevent React hydration errors (server HTML that does not match the first client render): - `hydration-proof`: a CLI and Node API. It loads every route of a server-rendered React app (Next.js, React Router, Remix, Astro, Vite SSR, custom servers) in a real browser, compares the server HTML with the hydrated DOM, and reports each difference with an issue code (HP1001–HP9010), the element, both values, a likely cause and the fix. Install: `npm install -D hydration-proof`, then `npx hydration-proof install` and `npx hydration-proof test`. Requires Node.js 22.18.0 or newer. - `eslint-plugin-hydration-proof`: 15 ESLint rules that catch the same causes in the editor (Date.now(), Math.random(), window, localStorage, matchMedia, locale and timezone formatting, unstable ids, invalid HTML nesting, suppressHydrationWarning misuse). Install: `npm install -D eslint-plugin-hydration-proof`. Requires ESLint 9 or 10 (flat config). - Error messages: every React 18 and 19 hydration error string has a page under /docs/errors, and every root cause a fix guide under /docs/causes. - Every page below is markdown. Append `.md` to any docs URL to get the same. - Everything in one file: https://hydration.jscrate.dev/llms-full.txt - Source: https://github.com/re-sohail/hydration-proof · Packages: https://www.npmjs.com/package/hydration-proof and https://www.npmjs.com/package/eslint-plugin-hydration-proof ## Overview - [Quick start](https://hydration.jscrate.dev/docs/quick-start.md): Install hydration-proof, run it against your Next.js, Remix or Astro app, and read the report: every React hydration mismatch, its cause and the fix. - [How it works](https://hydration.jscrate.dev/docs/how-it-works.md): How hydration-proof detects mismatches: it captures each page at six stages in a real browser, compares them, and explains every finding with a likely cause. - [Comparison](https://hydration.jscrate.dev/docs/comparison.md): Hydration error tools compared: the console, the Next.js dev overlay, react-hydration-overlay, Sentry, ESLint rules and hydration-proof, and when to use each. - [FAQ](https://hydration.jscrate.dev/docs/faq.md): React hydration error FAQ: short answers to the most asked questions, from error #418 and suppressHydrationWarning to useEffect, useId and next-themes. ## Learn hydration - [What is hydration?](https://hydration.jscrate.dev/docs/guides/what-is-hydration.md): What is hydration in React? How server HTML becomes an interactive page with hydrateRoot, what a mismatch means, and what Server Components change. - [React hydration errors](https://hydration.jscrate.dev/docs/guides/react-hydration-error.md): A React hydration error means the server HTML and the first client render differ. The messages in React 18 and 19, what causes each one, and how to fix it. - [Debugging hydration errors](https://hydration.jscrate.dev/docs/guides/debug-hydration-errors.md): How to debug a hydration error: read React's diff, find the component, rule out browser extensions, and trace production-only mismatches to their cause. - [Errors only in production](https://hydration.jscrate.dev/docs/guides/hydration-error-only-in-production.md): A React hydration error only in production usually means different data, timezone or HTML rewrites on the server. How to reproduce it, read #418 and fix it. - [suppressHydrationWarning](https://hydration.jscrate.dev/docs/guides/suppresshydrationwarning.md): What suppressHydrationWarning does in React, why it only works one level deep, when it is safe, and why you cannot turn hydration errors off in Next.js. - [useEffect and two-pass rendering](https://hydration.jscrate.dev/docs/guides/useeffect-two-pass-rendering.md): A useEffect hydration error means browser-only code ran during render. Effects never run on the server, so render the server's output first, then update. - [Client-only components](https://hydration.jscrate.dev/docs/guides/client-only-component.md): Build a ClientOnly Next.js component that renders a fallback on the server and its children after hydration, plus the Remix and TanStack versions. - [next/dynamic with ssr: false](https://hydration.jscrate.dev/docs/guides/next-dynamic-ssr-false.md): How next/dynamic ssr: false skips prerendering a component, why the App Router only allows it in Client Components, and when a ClientOnly wrapper is better. - [Zustand persist](https://hydration.jscrate.dev/docs/guides/zustand-hydration-error.md): A Zustand hydration error happens when persist loads saved state before hydration. Fix it with skipHydration and rehydrate(), or wait for hydration to finish. - [shadcn/ui](https://hydration.jscrate.dev/docs/guides/shadcn-hydration-error.md): A shadcn hydration error usually comes from dark mode, the Sidebar skeleton, dates in the Calendar, or a Button nested in a trigger. The fix for each one. - [Hydration errors and SEO](https://hydration.jscrate.dev/docs/guides/hydration-errors-seo.md): Do hydration errors affect SEO? Not as a ranking factor, but their effects can: content that differs, metadata React never fixes, slow pages, layout shift. ## Frameworks - [Next.js](https://hydration.jscrate.dev/docs/frameworks/nextjs.md): A Next.js hydration error means the server HTML and the browser's first render differ. The messages, common causes, fixes, and how to test every route. - [React Router](https://hydration.jscrate.dev/docs/frameworks/react-router.md): A React Router hydration error means the server HTML and the first client render differ. Causes in framework mode, HydrateFallback, and testing every route. - [Remix](https://hydration.jscrate.dev/docs/frameworks/remix.md): A Remix hydration error means the server HTML and the first client render differ. Common causes in Remix v2, ClientOnly, HydrateFallback, and route tests. - [Astro](https://hydration.jscrate.dev/docs/frameworks/astro.md): An Astro hydration error comes from a React island whose server HTML differs from its first client render. Causes, client directives, useId, and tests. - [Vite SSR](https://hydration.jscrate.dev/docs/frameworks/vite-ssr.md): Vite SSR hydration fails when entry-server and entry-client render different output. The setup, the common causes, duplicate React copies, and route tests. - [TanStack Start](https://hydration.jscrate.dev/docs/frameworks/tanstack-start.md): A TanStack Start hydration error means the server HTML and the first client render differ. The causes, ClientOnly, selective SSR, and how to test your routes. - [Custom React server](https://hydration.jscrate.dev/docs/frameworks/custom-server.md): A renderToPipeableStream hydration error means your server's HTML and the first hydrateRoot render differ. Fix it in Express or any Node.js server. ## Error messages - [All error messages](https://hydration.jscrate.dev/docs/errors.md): All React hydration error messages from React 18 and 19, with the minified code and a page that explains each. Find the text you see and go to the fix. - [Server rendered HTML didn't match](https://hydration.jscrate.dev/docs/errors/hydration-failed-server-rendered-html-didnt-match-client.md): Hydration failed because the server rendered HTML didn't match the client: how to read React 19's diff, find the value that differs and fix each cause. - [Initial UI does not match](https://hydration.jscrate.dev/docs/errors/hydration-failed-initial-ui-does-not-match.md): Hydration failed because the initial UI does not match what was rendered on the server: React 18's error, the warning that names the element, and fixes. - [Text content does not match](https://hydration.jscrate.dev/docs/errors/text-content-does-not-match-server-rendered-html.md): Text content does not match server-rendered HTML is React 18's error (#425) for text that differs between server and browser, usually a time, date or number. - [Attributes didn't match](https://hydration.jscrate.dev/docs/errors/tree-hydrated-but-attributes-didnt-match.md): A tree hydrated but some attributes of the server rendered HTML didn't match: React 19 kept the page but not the attribute. Why, and how to fix it for good. - [Prop className did not match](https://hydration.jscrate.dev/docs/errors/prop-classname-did-not-match.md): Prop className did not match: React 18 found a different class in the server HTML, usually from styled-components, Emotion, MUI or a theme. How to fix it. - [Expected server HTML to contain](https://hydration.jscrate.dev/docs/errors/expected-server-html-to-contain-a-matching.md): Expected server HTML to contain a matching div in div: React 18 rendered an element in the browser that the server HTML lacks. Each variant and its fix. - [Extra attributes from the server](https://hydration.jscrate.dev/docs/errors/extra-attributes-from-the-server.md): Warning: Extra attributes from the server means the page had attributes React did not render, often class and style from next-themes or a browser extension. - [Error while hydrating](https://hydration.jscrate.dev/docs/errors/there-was-an-error-while-hydrating.md): There was an error while hydrating means React gave up on the server HTML after an earlier error and rendered a Suspense boundary or the whole page again. - [div cannot be a descendant of p](https://hydration.jscrate.dev/docs/errors/div-cannot-be-a-descendant-of-p.md): In HTML, div cannot be a descendant of p: the browser closes the paragraph before the div, so hydration fails. Why, and how to fix it in your code or MUI. - [validateDOMNesting](https://hydration.jscrate.dev/docs/errors/validatedomnesting.md): validateDOMNesting warnings mean the browser will rearrange your HTML: a row without tbody, text in a tr, a link in a link. What each says and how to fix it. - [Minified React errors](https://hydration.jscrate.dev/docs/errors/minified-react-error-codes.md): Minified React error 418, 423, 425 and the other hydration codes (407, 419, 421, 422, 424) decoded: the React 18 and 19 message behind each, and the fix. - [React error #418](https://hydration.jscrate.dev/docs/errors/minified-react-error-418.md): Minified React error #418 is a hydration mismatch in a production build. What it means in React 18 and 19, how to get the full message, and how to fix it. - [React error #423](https://hydration.jscrate.dev/docs/errors/minified-react-error-423.md): Minified React error #423 means hydration failed outside any Suspense boundary and React re-rendered the whole page. Find the error that caused it and fix it. - [React error #425](https://hydration.jscrate.dev/docs/errors/minified-react-error-425.md): Minified React error #425 is React 18's text hydration mismatch in production: a date, time or number differs between server and browser. Find and fix it. - [Update before hydrating](https://hydration.jscrate.dev/docs/errors/suspense-boundary-received-update-before-hydrating.md): Suspense boundary received an update before it finished hydrating (#421): why an early update discards the server HTML, and the startTransition fix. - [Missing getServerSnapshot](https://hydration.jscrate.dev/docs/errors/missing-getserversnapshot.md): Missing getServerSnapshot means useSyncExternalStore ran on the server without its third argument. Add one that returns the same value on both sides. - [window is not defined](https://hydration.jscrate.dev/docs/errors/window-is-not-defined.md): ReferenceError: window is not defined: Next.js ran browser code on the server. Why a typeof window check causes a hydration error, and the fixes that work. ## Fix by cause - [All causes](https://hydration.jscrate.dev/docs/causes.md): The common causes of hydration errors in React and Next.js, how hydration-proof picks the cause of each finding, and the ESLint rule that catches each one. - [Time-dependent value](https://hydration.jscrate.dev/docs/causes/time.md): Why new Date() and Date.now() cause a Next.js date hydration error, and three fixes: pass the server time as a prop, render after mount, or format the date. - [Timezone difference](https://hydration.jscrate.dev/docs/causes/timezone.md): A timezone hydration mismatch: the server formats dates in UTC, the browser in the visitor's zone. Pass one explicit timeZone to both, or format after mount. - [Locale-dependent formatting](https://hydration.jscrate.dev/docs/causes/locale.md): A toLocaleString hydration mismatch happens when the server formats with its locale and the browser with the visitor's. Pass an explicit locale to both. - [Random value](https://hydration.jscrate.dev/docs/causes/random.md): Why a Math.random hydration error happens when render code calls Math.random(), crypto.randomUUID() or uuid, and how to pick the value once or use useId. - [Browser-only API used during render](https://hydration.jscrate.dev/docs/causes/browser-api.md): A browser API hydration mismatch happens when render code reads window or navigator, or branches on typeof window. Read browser values after mount instead. - [localStorage or sessionStorage read during render](https://hydration.jscrate.dev/docs/causes/storage.md): A localStorage hydration error happens when render code reads localStorage or sessionStorage. Render a neutral value first, then read storage after hydration. - [Screen size or media query read during render](https://hydration.jscrate.dev/docs/causes/media-query.md): A useMediaQuery Next.js hydration error happens when render code reads matchMedia or the window size. Use CSS media queries, or read the value after mount. - [Theme preference (dark or light mode)](https://hydration.jscrate.dev/docs/causes/theme.md): A next-themes hydration error comes from the class set on html before hydration or useTheme() in render. Suppress it on html; render theme UI after mount. - [Server and client used different data](https://hydration.jscrate.dev/docs/causes/data.md): A server/client data mismatch hydration error means the client rendered different data than the server. Send the server's data along; don't refetch it. - [Invalid HTML nesting](https://hydration.jscrate.dev/docs/causes/invalid-html.md): An invalid HTML nesting hydration error happens when the browser repairs markup, like a div in a p, before React hydrates. Fix the nesting to stop it. - [CSS-in-JS class names differ](https://hydration.jscrate.dev/docs/causes/css-in-js.md): A styled-components hydration error means the server and browser generated different class names. Turn on the compiler and add a style registry. - [Browser extension](https://hydration.jscrate.dev/docs/causes/extension.md): A browser extension hydration error comes from Grammarly, ColorZilla or a password manager editing the page before React hydrates. Confirm it, then ignore it. - [A script changed the page before hydration](https://hydration.jscrate.dev/docs/causes/third-party-script.md): A next/script hydration error happens when a script edits the server HTML before React hydrates. Load it afterInteractive or lazyOnload instead. - [HTML rewritten by a CDN or proxy](https://hydration.jscrate.dev/docs/causes/cdn.md): A Cloudflare Auto Minify hydration error happens when a CDN rewrites server HTML on its way to the browser. Turn off HTML minification and email obfuscation. - [Generated id differs](https://hydration.jscrate.dev/docs/causes/unstable-id.md): A React useId hydration error means an id differs between server and client: a counter, a random value, or useId in trees that differ. How to fix each. - [Server Action form state](https://hydration.jscrate.dev/docs/causes/form-state.md): Server Action form state hydration breaks when the server renders a submitted form and the client hydrates without its state. Let the framework pass it on. - [Intentional difference (suppressHydrationWarning)](https://hydration.jscrate.dev/docs/causes/suppressed.md): An intentional hydration mismatch is a difference you accept, like a timestamp. Put suppressHydrationWarning on the smallest element and audit what it hides. ## Test with the CLI - [CLI](https://hydration.jscrate.dev/docs/cli.md): The hydration-proof CLI reference: every command (test, baseline, merge-reports, dev, ui, init, migrate, install, doctor), its flags and the exit codes. - [Configuration](https://hydration.jscrate.dev/docs/configuration.md): Every hydration-proof config option: the file, defineConfig, and the server, routes, scenarios, matrix, probes, ready, checks, ignore, CI and hooks settings. - [Routes](https://hydration.jscrate.dev/docs/routes.md): How to test every route for hydration errors: route discovery per framework, example values for dynamic routes, sitemaps, crawling, globs and the route cache. - [Scenarios and sign-in](https://hydration.jscrate.dev/docs/scenarios.md): Test signed-in pages for hydration errors with scenarios: locale, timezone, theme and viewport presets, session cookies, storage state, a login and API mocks. - [Environment matrix](https://hydration.jscrate.dev/docs/environment-matrix.md): Use the matrix option to test locales and timezones for hydration errors, plus themes, viewports and browsers, in a small set of pairwise runs. - [Probes](https://hydration.jscrate.dev/docs/probes.md): Run hydration-proof with --probe to prove the cause of a hydration mismatch: each page is reloaded with one thing changed, such as the clock or the locale. - [Interactions and navigation](https://hydration.jscrate.dev/docs/interactions.md): Find lost clicks before hydration, input that React resets, lost focus and scroll, and pages that differ after client-side navigation, on every route. - [Ignoring findings](https://hydration.jscrate.dev/docs/ignoring.md): Ignore known hydration mismatches without hiding new ones: skip elements and attributes, mask text, or accept one finding with a reason and an expiry date. - [Reports](https://hydration.jscrate.dev/docs/reports.md): Each hydration error report (SARIF, JUnit, JSON, HTML, GitHub, GitLab) that hydration-proof writes: what it contains, where it goes and how CI reads it. - [CI](https://hydration.jscrate.dev/docs/ci.md): Detect hydration errors in CI with GitHub Actions, GitLab CI or CircleCI: complete workflows, SARIF upload, browser caching, sharding and --changed. - [Baselines and budgets](https://hydration.jscrate.dev/docs/baselines.md): Adopt hydration-proof on an app with existing problems: a hydration error baseline and budget let CI fail only on new findings, with owners and trends. - [Dev overlay](https://hydration.jscrate.dev/docs/dev-overlay.md): hydration-proof dev opens your app with a hydration error overlay: every page you open is checked, with the element, both values, the cause and source line. - [Playwright](https://hydration.jscrate.dev/docs/playwright.md): Find every Playwright hydration error your e2e suite misses: hydration-proof drives Playwright, waits for React to hydrate and reuses your browsers and login. - [Node API](https://hydration.jscrate.dev/docs/node-api.md): The hydration-proof Node API: run tests from a script with run(), read and merge reports, define configs, plugins and adapters, and use the stable exit codes. - [Monorepos](https://hydration.jscrate.dev/docs/monorepos.md): Run hydration tests in a monorepo with one command: list each app under projects, keep a config per app, pick one with --project and get one combined report. - [Adapters](https://hydration.jscrate.dev/docs/adapters.md): hydration-proof adapters build, start and find the routes of Next.js, React Router, Remix, Astro and Vite SSR apps, or write your own with defineAdapter. - [Plugins](https://hydration.jscrate.dev/docs/plugins.md): hydration-proof plugins teach the tool about your app: markup to ignore, causes it cannot guess, routes from a CMS, custom reporters and adapters. - [Security](https://hydration.jscrate.dev/docs/security.md): hydration-proof security: no telemetry, requests only to the app under test, redacted reports, a locked-down local dashboard and one runtime dependency. - [Troubleshooting](https://hydration.jscrate.dev/docs/troubleshooting.md): hydration-proof troubleshooting: fix a missing browser, an app that won't start, skipped routes, failed logins, pages that never settle, missing source lines. - [Compatibility](https://hydration.jscrate.dev/docs/compatibility.md): hydration-proof compatibility: supported Node.js, React, Next.js, framework, browser and package manager versions, what is stable, and how deprecation works. ## ESLint plugin - [Getting started](https://hydration.jscrate.dev/docs/eslint.md): eslint-plugin-hydration-proof adds an ESLint rule for hydration mismatch causes of each kind to React and Next.js: 15 flat-config rules, three presets. - [All rules](https://hydration.jscrate.dev/docs/rules.md): All 15 ESLint rules for React hydration in eslint-plugin-hydration-proof, grouped by the mismatch they catch, with their severity in each preset. - [no-date-in-render](https://hydration.jscrate.dev/docs/rules/no-date-in-render.md): Calling Date.now() in render, new Date() or performance.now() gives the server and the browser different times. This rule reports it and shows the fix. - [no-random-in-render](https://hydration.jscrate.dev/docs/rules/no-random-in-render.md): Math.random() in render, crypto.randomUUID(), uuid and nanoid return a new value on each render, so hydration fails. This rule reports them in React code. - [no-browser-global-in-render](https://hydration.jscrate.dev/docs/rules/no-browser-global-in-render.md): Reading window in render: React runs that code on the server too, where window, document and navigator do not exist. This rule reports those reads. - [no-storage-in-initial-render](https://hydration.jscrate.dev/docs/rules/no-storage-in-initial-render.md): Reading localStorage in useState or anywhere in render makes the server render the default and the browser the stored value. This rule reports it. - [no-match-media-in-render](https://hydration.jscrate.dev/docs/rules/no-match-media-in-render.md): A matchMedia SSR mismatch happens when a component evaluates a media query in render. This rule reports matchMedia() calls and shows the fixes. - [no-locale-without-explicit-locale](https://hydration.jscrate.dev/docs/rules/no-locale-without-explicit-locale.md): Calling toLocaleString without a locale formats with the runtime's default, which differs on the server and in the browser. This rule reports it. - [no-timezone-without-explicit-timezone](https://hydration.jscrate.dev/docs/rules/no-timezone-without-explicit-timezone.md): Without the Intl.DateTimeFormat timeZone option, dates format in the server's zone and then in the browser's, so hydration fails. This rule reports it. - [no-unstable-id](https://hydration.jscrate.dev/docs/rules/no-unstable-id.md): Use useId instead of a random id, timestamp or counter: those differ between the server render and hydration. This rule reports every unstable id. - [no-global-render-counter](https://hydration.jscrate.dev/docs/rules/no-global-render-counter.md): A module-level counter (SSR id, item number, render count) changed during render never matches the value in the browser. This rule reports the write. - [no-window-render-branch](https://hydration.jscrate.dev/docs/rules/no-window-render-branch.md): The typeof window !== 'undefined' hydration mismatch: the check is false on the server and true in the browser. This rule reports render branches on it. - [no-invalid-interactive-nesting](https://hydration.jscrate.dev/docs/rules/no-invalid-interactive-nesting.md): When you nest a button inside button, React markup gets repaired by the browser before hydration. This rule reports that, a div in a p and table rows. - [audit-suppress-hydration-warning](https://hydration.jscrate.dev/docs/rules/audit-suppress-hydration-warning.md): A suppressHydrationWarning ESLint rule: it reports the attribute where it does nothing or hides more than intended, and in strict mode every use. - [no-client-only-initial-state](https://hydration.jscrate.dev/docs/rules/no-client-only-initial-state.md): A useState initial value (window.innerWidth, navigator, a typeof window check) differs on the server and in the browser. This rule reports it in React. - [require-stable-server-snapshot](https://hydration.jscrate.dev/docs/rules/require-stable-server-snapshot.md): useSyncExternalStore needs a getServerSnapshot that returns the same value on the server and during hydration. This rule reports a missing or unstable one. - [require-deterministic-list-order](https://hydration.jscrate.dev/docs/rules/require-deterministic-list-order.md): A localeCompare sort hydration mismatch, a random comparator or a shuffle orders a list differently on the server and in the browser. This rule reports it. ## Compare - [Next.js dev overlay](https://hydration.jscrate.dev/docs/compare/nextjs-dev-overlay.md): The Next.js dev overlay hydration error view shows one mismatch on the page you have open. hydration-proof tests every route, in CI and in production builds. - [react-hydration-overlay](https://hydration.jscrate.dev/docs/compare/react-hydration-overlay.md): A react-hydration-overlay alternative that adds no code to your app: test every route in CI and production builds, with the element, values and cause. - [Sentry](https://hydration.jscrate.dev/docs/compare/sentry-hydration-errors.md): A Sentry hydration error issue shows what broke for real users after deploy. hydration-proof finds mismatches before deploy. How the two fit together. - [eslint-plugin-react-hooks](https://hydration.jscrate.dev/docs/compare/eslint-plugin-react-hooks.md): The eslint-plugin-react-hooks purity rule flags Date.now() and Math.random() in render. What it catches, what hydration needs beyond it, and how to run both. - [eslint-plugin-validate-jsx-nesting](https://hydration.jscrate.dev/docs/compare/eslint-plugin-validate-jsx-nesting.md): The ESLint no-invalid-jsx-nesting rule checks direct parent and child tags. What it catches, what it misses, and how hydration-proof's nesting rule differs. ## Issue codes - [All issue codes](https://hydration.jscrate.dev/docs/issues.md): The hydration-proof issue codes: what each HP code means, its default severity, how to fix it and how to ignore it, from HP1001 text mismatches to HP9010. - [HP1001 text-mismatch](https://hydration.jscrate.dev/docs/issues/hp1001.md): HP1001 (text mismatch) means the server HTML has different text than React rendered in the browser. The likely causes, the fix for each, and an example. - [HP1002 attribute-mismatch](https://hydration.jscrate.dev/docs/issues/hp1002.md): HP1002 (attribute mismatch): an attribute has one value in the server HTML and another in React's client render, and React never fixes it. Causes and fixes. - [HP1003 style-mismatch](https://hydration.jscrate.dev/docs/issues/hp1003.md): HP1003 (style mismatch): the style attribute in the server HTML differs from the inline style React applies on the client, and React keeps the server's. - [HP1004 class-mismatch](https://hydration.jscrate.dev/docs/issues/hp1004.md): HP1004 (class mismatch): the class attribute in the server HTML differs from React's className, often a theme or CSS-in-JS. The page keeps the server classes. - [HP1005 extra-attribute](https://hydration.jscrate.dev/docs/issues/hp1005.md): HP1005 (extra attribute): the server HTML has an attribute React does not render on the client, so it stays on the page. What causes it and how to fix it. - [HP1006 missing-attribute](https://hydration.jscrate.dev/docs/issues/hp1006.md): HP1006 (missing attribute): React renders an attribute on the client that the server HTML lacks, and hydration never adds it. The causes and how to fix it. - [HP1007 element-mismatch](https://hydration.jscrate.dev/docs/issues/hp1007.md): HP1007 (element mismatch): the server rendered one element and the client another in the same place, so React threw the server HTML away. Causes and fixes. - [HP1008 extra-element](https://hydration.jscrate.dev/docs/issues/hp1008.md): HP1008 (extra element): the server HTML contains a node the client render does not produce, so React discards that part of the page. Causes and the fix. - [HP1009 missing-element](https://hydration.jscrate.dev/docs/issues/hp1009.md): HP1009 (missing element): React's client render produces a node the server HTML does not contain, so React re-renders that part. Causes and how to fix it. - [HP1010 branch-replaced](https://hydration.jscrate.dev/docs/issues/hp1010.md): HP1010 (branch replaced): hydration failed inside a branch, so React threw its server HTML away and rendered it on the client. Why it costs you, and the fix. - [HP1011 root-replaced](https://hydration.jscrate.dev/docs/issues/hp1011.md): HP1011 (root replaced): hydration failed outside any Suspense boundary, so React threw away the whole server-rendered page and rendered it again. The fix. - [HP1012 form-state-mismatch](https://hydration.jscrate.dev/docs/issues/hp1012.md): HP1012 (form state mismatch): a form control's value, checked or selected state changed during hydration, and React never reports it. Causes and the fix. - [HP1013 inner-html-mismatch](https://hydration.jscrate.dev/docs/issues/hp1013.md): HP1013 (inner HTML mismatch): the HTML injected with dangerouslySetInnerHTML differs between server and client, and React never patches it. Causes and fix. - [HP1014 head-mismatch](https://hydration.jscrate.dev/docs/issues/hp1014.md): HP1014 (head mismatch): the title, meta tags or stylesheets in the head changed while the page hydrated, so crawlers and link previews see other values. - [HP1015 whitespace-mismatch](https://hydration.jscrate.dev/docs/issues/hp1015.md): HP1015 (whitespace mismatch): only whitespace differs between the server HTML and React's render, which usually means a CDN or proxy minified the HTML. - [HP2001 react-hydration-error](https://hydration.jscrate.dev/docs/issues/hp2001.md): HP2001 (React hydration error): React said hydration failed, but the DOM comparison could not locate the difference. How to find it, and what #418 means. - [HP2002 react-hydration-warning](https://hydration.jscrate.dev/docs/issues/hp2002.md): HP2002 (React hydration warning): React logged a hydration mismatch warning in a development build that no DOM finding explains. What it means and what to do. - [HP2003 boundary-client-rendered](https://hydration.jscrate.dev/docs/issues/hp2003.md): HP2003 (boundary client rendered): React could not hydrate a Suspense boundary and rendered it on the client instead (React error #422). What to check first. - [HP2004 root-client-rendered](https://hydration.jscrate.dev/docs/issues/hp2004.md): HP2004 (root client rendered): an error during hydration outside any Suspense boundary made React render the whole page on the client (React error #423). - [HP2005 update-before-hydration](https://hydration.jscrate.dev/docs/issues/hp2005.md): HP2005 (update before hydration): a Suspense boundary or root got an update before it finished hydrating (React errors 421, 424). Fix it with startTransition. - [HP2006 server-render-error](https://hydration.jscrate.dev/docs/issues/hp2006.md): HP2006 (server render error): the server failed to render a Suspense boundary, so the browser had to render it (React error #419). Where to look and the fix. - [HP2007 page-error](https://hydration.jscrate.dev/docs/issues/hp2007.md): HP2007 (page error): a script threw an uncaught error while the page loaded. It may or may not be related to hydration. How to read it, fix it or ignore it. - [HP3001 invalid-nesting](https://hydration.jscrate.dev/docs/issues/hp3001.md): HP3001 (invalid-nesting) means the server HTML nests elements in a way HTML forbids, such as a div in a p. Why the browser repairs it and how to fix it. - [HP3002 nested-interactive](https://hydration.jscrate.dev/docs/issues/hp3002.md): HP3002 (nested-interactive) means a link is inside a link, a button inside a button or a form inside a form. How the browser splits them and how to fix it. - [HP3003 duplicate-id](https://hydration.jscrate.dev/docs/issues/hp3003.md): HP3003 (duplicate-id) means several elements on the page share one id, so labels and ARIA references find only the first. Generate the ids with useId. - [HP3004 duplicate-use-id](https://hydration.jscrate.dev/docs/issues/hp3004.md): HP3004 (duplicate-use-id) means several React roots on one page call useId without an identifierPrefix and generate the same ids. Give each root a prefix. - [HP4001 pre-hydration-mutation](https://hydration.jscrate.dev/docs/issues/hp4001.md): HP4001 (pre-hydration-mutation) means a script, extension or third-party tag changed the server HTML before React hydrated it. Find the script and move it. - [HP4002 extension-mutation](https://hydration.jscrate.dev/docs/issues/hp4002.md): HP4002 (extension-mutation) means a browser extension such as a grammar checker or password manager changed the page before hydration. When to ignore it. - [HP4003 html-rewritten](https://hydration.jscrate.dev/docs/issues/hp4003.md): HP4003 (html-rewritten) means a CDN, proxy or edge function changed the HTML your server produced before the browser got it. Turn off that HTML rewriting. - [HP5001 lost-interaction](https://hydration.jscrate.dev/docs/issues/hp5001.md): HP5001 (lost-interaction) means a click made while the page loaded did nothing, because the button looked ready before React handled events. How to fix it. - [HP5002 input-reset](https://hydration.jscrate.dev/docs/issues/hp5002.md): HP5002 (input-reset) means text typed or a box checked before hydration finished was cleared or replaced. Keep what users type with uncontrolled inputs. - [HP5003 focus-lost](https://hydration.jscrate.dev/docs/issues/hp5003.md): HP5003 (focus-lost) means the field a user focused, or the text they selected, was lost while the page hydrated. Why it happens and how to keep focus. - [HP5004 navigation-mismatch](https://hydration.jscrate.dev/docs/issues/hp5004.md): HP5004 (navigation-mismatch) means a route renders different content when reached through the app's router than when its URL is loaded directly. Fix it. - [HP5005 navigation-error](https://hydration.jscrate.dev/docs/issues/hp5005.md): HP5005 (navigation-error) means navigating to a route inside the app threw an error, its RSC or data request failed, or the URL never changed. How to fix it. - [HP5006 double-handler](https://hydration.jscrate.dev/docs/issues/hp5006.md): HP5006 (double-handler) means a script listener or inline on* attribute handles an event React also handles on that element, so one click can run twice. - [HP5007 scroll-reset](https://hydration.jscrate.dev/docs/issues/hp5007.md): HP5007 (scroll-reset) means the page scrolled on its own while it hydrated, so a user who had already scrolled lost their place. Why and how to fix it. - [HP5008 interaction-failed](https://hydration.jscrate.dev/docs/issues/hp5008.md): HP5008 (interaction-failed) means an interaction from your config threw an error or caused a page error. Run it in a headed browser to see where it fails. - [HP6001 suppressed-mismatch](https://hydration.jscrate.dev/docs/issues/hp6001.md): HP6001 (suppressed-mismatch) lists a server and client difference hidden by suppressHydrationWarning. When it is fine, and when it hides a real bug. - [HP6002 suppression-hides-structure](https://hydration.jscrate.dev/docs/issues/hp6002.md): HP6002 (suppression-hides-structure) means suppressHydrationWarning is set, but the elements inside still differ, so React re-renders them. How to fix it. - [HP6003 suppression-unused](https://hydration.jscrate.dev/docs/issues/hp6003.md): HP6003 (suppression-unused) means an element has suppressHydrationWarning but its server and client output are identical. Remove it before it hides a bug. - [HP9001 hydration-timeout](https://hydration.jscrate.dev/docs/issues/hp9001.md): HP9001 (hydration-timeout) means React loaded but hydration did not finish before the timeout. Raise the timeout or find the Suspense boundary that hangs. - [HP9002 no-react](https://hydration.jscrate.dev/docs/issues/hp9002.md): HP9002 (no-react) means the page loaded without any React renderer, so nothing was hydrated or tested. Check the URL and that the page's scripts load. - [HP9003 client-rendered-page](https://hydration.jscrate.dev/docs/issues/hp9003.md): HP9003 (client-rendered-page) means React mounted the page with createRoot instead of hydrating server HTML, so there was nothing to compare. What to check. - [HP9004 navigation-failed](https://hydration.jscrate.dev/docs/issues/hp9004.md): HP9004 (navigation-failed) means the test browser could not navigate to the URL at all: the server is not running, the URL is wrong or the connection failed. - [HP9005 http-error](https://hydration.jscrate.dev/docs/issues/hp9005.md): HP9005 (http-error) means the page's document response had an HTTP error status such as 404 or 500. Fix the route, or list the status the route should return. - [HP9006 body-unavailable](https://hydration.jscrate.dev/docs/issues/hp9006.md): HP9006 (body-unavailable) means the document body could not be read, so the checks that start from the server HTML were skipped on that page. What to check. - [HP9007 capture-truncated](https://hydration.jscrate.dev/docs/issues/hp9007.md): HP9007 (capture-truncated) means buffers overflowed while the page was captured, so its results may be incomplete. Why it happens and what to do about it. - [HP9008 no-root](https://hydration.jscrate.dev/docs/issues/hp9008.md): HP9008 (no-root) means a React renderer loaded on the page but no root was created before the timeout, so nothing was hydrated. Find what stopped the entry. - [HP9009 ready-timeout](https://hydration.jscrate.dev/docs/issues/hp9009.md): HP9009 (ready-timeout) means the page kept changing, or your ready selector or function never passed, before the timeout. How to set the ready options. - [HP9010 unexpected-redirect](https://hydration.jscrate.dev/docs/issues/hp9010.md): HP9010 (unexpected-redirect) means a route ended on a different URL than requested. For signed-in scenarios that land on a login page, the login did not work. ## Optional - [Releases](https://hydration.jscrate.dev/docs/releases.md): hydration-proof releases: every version of the CLI and the ESLint plugin, how versions are numbered, how to upgrade with migrate, and the history up to 1.0. - [About](https://hydration.jscrate.dev/docs/about.md): About hydration-proof: the open-source CLI and ESLint plugin for React hydration errors, its principles, its author, the MIT license and how to report issues. - [GitHub releases](https://github.com/re-sohail/hydration-proof/releases): Full release notes for every version.