# HP2005: An update arrived before hydration finished

> HP2005 (update before hydration): a Suspense boundary or root got an update before it finished hydrating (React errors 421, 424). Fix it with startTransition.

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

HP2005 (`update-before-hydration`) means a state or context update reached a
Suspense boundary, or the root, before React had finished hydrating it, and
React switched it to client rendering (React errors #421 and #424). Wrap updates that run during hydration in
`startTransition`.

| | |
| --- | --- |
| Code | `HP2005` |
| Name | `update-before-hydration` |
| Default severity | Warning |
| Group | Problems React reported |
| What it means | A Suspense boundary or root received an update before it finished hydrating (React errors 421/424). |

## What HP2005 (`update-before-hydration`) means

Hydration is not instant: React hydrates the root first and each Suspense
boundary when its code and content are ready. If something updates state that a
not-yet-hydrated boundary depends on (a context value set in an effect, a parent
re-rendering on load), React has to render the new state right away, cannot
use the server HTML for it, and renders the boundary on the client instead.

The page keeps working, but that part's server HTML is thrown away and
rendered a second time.

## The React error it matches

```text
This Suspense boundary received an update before it finished hydrating.
```

React logs this for a boundary; production builds show #421, or #424 when the
root itself received the update. See
[Suspense boundary received an update before it finished hydrating](https://hydration.jscrate.dev/docs/errors/suspense-boundary-received-update-before-hydrating)
and the [minified React error codes](https://hydration.jscrate.dev/docs/errors/minified-react-error-codes).

## Likely causes

- A provider that sets state in an effect on load, such as a user or theme read
  from [browser storage](https://hydration.jscrate.dev/docs/causes/storage), while boundaries below it are
  still hydrating.
- A parent that re-renders with new props on mount, for example after reading
  a [media query](https://hydration.jscrate.dev/docs/causes/media-query).

## How to fix it

- Wrap updates triggered during hydration in `startTransition`.

An update in an effect is urgent by default:

```tsx title="user-provider.tsx"
"use client";

import { createContext, useEffect, useState, type ReactNode } from "react";

export const UserContext = createContext<string | null>(null);

export function UserProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<string | null>(null);

  useEffect(() => {
    setUser(localStorage.getItem("user"));
  }, []);

  return <UserContext.Provider value={user}>{children}</UserContext.Provider>;
}
```

Marked as a transition, it can wait for the boundaries below to finish
hydrating instead of forcing them to render on the client:

```tsx title="user-provider.tsx"
"use client";

import {
  createContext,
  startTransition,
  useEffect,
  useState,
  type ReactNode,
} from "react";

export const UserContext = createContext<string | null>(null);

export function UserProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<string | null>(null);

  useEffect(() => {
    startTransition(() => {
      setUser(localStorage.getItem("user"));
    });
  }, []);

  return <UserContext.Provider value={user}>{children}</UserContext.Provider>;
}
```

## Example

```text
  ⚠ /account 1.4s  1 warning
    HP2005 An update arrived before hydration finished
      This Suspense boundary received an update before it finished hydrating. This caused the boundary to switch to client rendering. The usual way to fix this is to wrap the original update in startTransition.
      → Wrap updates triggered during hydration in startTransition.
```

## Related

- [HP2003: a Suspense boundary switched to client rendering](https://hydration.jscrate.dev/docs/issues/hp2003)
- [HP2006: the server could not finish a boundary](https://hydration.jscrate.dev/docs/issues/hp2006)
- [Suspense boundary received an update before hydrating](https://hydration.jscrate.dev/docs/errors/suspense-boundary-received-update-before-hydrating)
- [useEffect and two-pass rendering](https://hydration.jscrate.dev/docs/guides/useeffect-two-pass-rendering)
