Hydration Proof

Search documentation

Find a page or section

HP9003: The page is rendered on the client only

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.

HP9003 (client-rendered-page) means React mounted this page with createRoot instead of hydrating server HTML with hydrateRoot. There is no server HTML to compare, so hydration-proof has nothing to test on it. That is expected for a single-page app; if the page should be server-rendered, check its entry point.

CodeHP9003
Nameclient-rendered-page
Default severityInfo
GroupTest run problems
What it meansReact mounted with createRoot instead of hydrating server HTML.

What the HP9003 client rendered page finding means

hydration-proof sees every React root the page creates. When the page's root is a client root and nothing was hydrated, it reports:

React mounted with createRoot; there is no server HTML to hydrate.

A client root that mounts before the hydrating one (a widget, a toast container) does not trigger it: hydration-proof waits a moment for the hydrating root first.

It is info: it does not fail the run, and it is not printed in the terminal list. The HTML and JSON reports show it.

Likely causes

  • A single-page app, or a route that is rendered only in the browser.
  • A page whose whole content is a client-only component, such as next/dynamic with ssr: false at the top.
  • A custom server that sends an empty container and calls createRoot in the entry file.

How to fix it

There is nothing to fix if the page is meant to render on the client.

  • If the route is client-only by design, leave it out with routes.exclude, or ignore code: "HP9003" for it with a reason (see ignoring findings).
  • If the page should be server-rendered, check that the server renders the app's HTML into the container and that the client entry calls hydrateRoot:
entry-client.tsx
import { hydrateRoot } from "react-dom/client";
import { App } from "./app";
 
hydrateRoot(document.getElementById("root")!, <App />);