# 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.

Source: https://hydration.jscrate.dev/docs/issues/hp9003
Last updated: 2026-09-18

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.

| | |
| --- | --- |
| Code | `HP9003` |
| Name | `client-rendered-page` |
| Default severity | Info |
| Group | Test run problems |
| What it means | React 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:

```text
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](https://hydration.jscrate.dev/docs/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`](https://hydration.jscrate.dev/docs/guides/next-dynamic-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](https://hydration.jscrate.dev/docs/ignoring)).
- 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`:

```tsx title="entry-client.tsx"
import { hydrateRoot } from "react-dom/client";
import { App } from "./app";

hydrateRoot(document.getElementById("root")!, <App />);
```

## Related

- [HP9002: no React found on the page](https://hydration.jscrate.dev/docs/issues/hp9002)
- [HP9008: React loaded but never mounted a root](https://hydration.jscrate.dev/docs/issues/hp9008)
- [Client-only components](https://hydration.jscrate.dev/docs/guides/client-only-component)
- [Testing a custom React server](https://hydration.jscrate.dev/docs/frameworks/custom-server)
