Hydration Proof

Search documentation

Find a page or section

Every finding has a stable code, and every code has a page.

Every finding carries one of the hydration-proof issue codes: HP1001 for text that differs between server and client, HP3001 for invalid HTML nesting, and so on. A code never changes meaning, so you can use it in ignore rules, baselines and budgets. Each code below links to a page with its causes and fixes.

How to read a code

The first digit is the group. Each code also has a kebab-case name (text-mismatch) that is as stable as the code itself.

CodesGroupWhat went wrong
HP1xxxDOM mismatchesThe server HTML and the first client render differ
HP2xxxProblems React reportedReact logged an error or warning no DOM finding explains, or a script threw
HP3xxxMarkup the browser repairedThe HTML parser rewrote invalid markup, or ids collide
HP4xxxChanges made outside ReactA script, extension, CDN or proxy changed the page
HP5xxxInteraction during hydrationInput, clicks, focus, scroll or navigation broke while the page hydrated
HP6xxxsuppressHydrationWarning auditWhat suppressHydrationWarning hides, or fails to hide
HP9xxxTest run problemsThe page could not be tested properly

The code shows up everywhere a finding does: the terminal, report.json, the HTML report, the SARIF rule id, the JUnit failure type and the GitLab check_name. See report formats for each one.

Severity and --fail-on

Every code has a default severity. It decides whether the run fails:

SeverityTerminalFails the run
errorListed, the page is marked failedBy default
warningListed, the page is marked with a warningWith --fail-on warning or --fail-on info
infoNot listed; in the JSON and HTML reportsOnly with --fail-on info

--fail-on never (or ci.failOn: 'never') never fails the run, and ci.maxWarnings fails it when there are more warnings than you allow. A finding's severity is usually its code's default; a few are raised or lowered. For example, a difference hidden by suppressHydrationWarning that does not look intentional is a warning instead of info. Budgets per severity, route or code are covered in baselines and budgets.

Ignore a code

Ignored findings stay in the report, marked as ignored, and do not fail the run. A rule needs a reason, and an expiry date keeps a temporary exception from becoming permanent: once it passes, the finding fails the run again.

hydration-proof.config.ts
import { defineConfig } from "hydration-proof";
 
export default defineConfig({
  ignore: {
    issues: [
      {
        code: "HP1004",
        route: "/legacy/**",
        reason: "Old theme system",
        expires: "2026-12-31",
      },
    ],
  },
});

A rule can match a code, a route glob, a selector or a fingerprint. Ignoring findings covers selectors, attributes and text patterns as well.

Fingerprints

Every finding also has a fingerprint. It stays the same across runs as long as the problem is the same: same code, route pattern, element and attribute. Ignore rules and baselines match on it, and the SARIF report passes it to code scanning, so an alert is recognized from one run to the next.

DOM mismatches

The server HTML and the first client render differ: text, attributes, inline styles, class names, elements, whitespace, form state or the document head. It also covers the branches React threw away and rendered again on the client.

CodeTitleSeverity
HP1001Text differs between server and clientError
HP1002Attribute differs between server and clientError
HP1003Inline style differs between server and clientError
HP1004Class name differs between server and clientError
HP1005Attribute only present in the server HTMLWarning
HP1006Attribute missing from the server HTMLError
HP1007Different element rendered on server and clientError
HP1008Element only present in the server HTMLError
HP1009Element missing from the server HTMLError
HP1010React discarded server HTML and rendered a branch againError
HP1011React discarded the whole server-rendered pageError
HP1012Form state differs between server and clientWarning
HP1013dangerouslySetInnerHTML differs between server and clientError
HP1014Document head differs between server and clientWarning
HP1015Whitespace differs between server and clientError

Problems React reported

Errors and warnings React logged itself. When a DOM finding explains them, React's message is attached to that finding as evidence instead; these codes are for the reports nothing else explains, and for page errors.

CodeTitleSeverity
HP2001React reported a hydration errorError
HP2002React warned about a hydration mismatchWarning
HP2003A Suspense boundary switched to client renderingError
HP2004The root switched to client renderingError
HP2005An update arrived before hydration finishedWarning
HP2006The server could not finish rendering a boundaryError
HP2007Uncaught error while loading the pageWarning

Markup the browser repaired

Nesting the HTML parser rewrites before React hydrates, nested interactive elements, duplicate ids and useId collisions between React roots.

CodeTitleSeverity
HP3001Invalid HTML nestingError
HP3002Interactive element nested in anotherError
HP3003Duplicate id attributeInfo
HP3004Two React roots generate the same idsWarning

Changes made outside React

Scripts, browser extensions, CDNs and proxies that changed the page before React hydrated it.

CodeTitleSeverity
HP4001The page was modified before React hydratedError
HP4002A browser extension changed the pageInfo
HP4003HTML was rewritten between the server and the browserError

Interaction during hydration

What a user does before the page is interactive, and client-side navigation compared with a direct load. Most of these need checks.interactions or checks.navigation.

CodeTitleSeverity
HP5001An interaction before hydration was lostWarning
HP5002User input was reset during hydrationError
HP5003Focus was lost during hydrationWarning
HP5004The page differs after client-side navigationWarning
HP5005Client-side navigation failedError
HP5006An element handles the same event twiceWarning
HP5007Scroll position was reset during hydrationWarning
HP5008A custom interaction failedError

suppressHydrationWarning audit

Differences that suppressHydrationWarning hides, structural differences it cannot hide, and suppressions with nothing to suppress.

CodeTitleSeverity
HP6001Mismatch hidden by suppressHydrationWarningInfo
HP6002suppressHydrationWarning cannot hide a structural differenceError
HP6003suppressHydrationWarning with nothing to suppressInfo

Test run problems

The page did not load, React never hydrated, or the page never settled.

CodeTitleSeverity
HP9001Hydration did not finish in timeError
HP9002No React found on the pageWarning
HP9003The page is rendered on the client onlyInfo
HP9004The page could not be loadedError
HP9005The server answered with an error statusError
HP9006The server HTML could not be capturedWarning
HP9007Some capture data was droppedWarning
HP9008React loaded but never mounted a rootWarning
HP9009The page never became quietWarning
HP9010The route redirected somewhere elseWarning