Hydration mismatch on /login (lazy route SSR) in apps/backoffice #27

Open
opened 2026-07-04 12:11:09 +00:00 by momsse · 0 comments
Owner

Migré depuis viziertronic/octant#70 — ouvert le 2026-06-23 par @momsse.

Summary

React hydration mismatch on the backoffice /login route: the server-rendered HTML does not match the client tree, so React discards and regenerates the subtree on the client.

Observed in apps/backoffice running pnpm dev (Vite + TanStack Start SSR, React 19), when loading http://localhost:3000/login.

Console error

Error: Hydration failed because the server rendered HTML didn't match the client.
As a result this tree will be regenerated on the client.

  <DialogsProvider>
    <OutletImpl>
      <Suspense fallback={null}>
        <MatchImpl matchId="/(auth)/lo...">
          <MatchView ...>
            ...
              <MatchInnerImpl matchId="/(auth)/lo...">
                <Lazy>
                  <LoginPage>
+                   <main className="flex min-h-screen items-center justify-center">
-                   <Suspense>

The diff points at the LoginPage boundary: the client renders <main> while the server emitted a <Suspense> placeholder — i.e. the lazy route component is resolved on the client but was still suspended/fallback during SSR.

Steps to reproduce

  1. pnpm --filter @octant/backoffice dev
  2. Open http://localhost:3000/login
  3. Observe the hydration-mismatch exception in the browser console on first load.

Suspected cause

TanStack Start SSR renders the lazy-loaded route component inside a <Suspense> boundary; the server emits the fallback while the client resolves the real component, producing a structural mismatch on hydration. Likely affects other lazy routes too, not just /login.

Scope / notes

  • Reproduced on the PR #65 (split/13-backoffice) branch. routes/(auth)/login.tsx and routes/__root.tsx are unchanged by recent review fixes, so this appears to be a scaffold-level SSR/lazy-route issue rather than a regression from those fixes.
  • The page still renders and works after the client regeneration, but the mismatch should be resolved to avoid the SSR penalty and console noise.

Environment

  • apps/backoffice — TanStack Start (SSR), React 19, Vite 7 (vite dev)
> _Migré depuis [viziertronic/octant#70](https://github.com/viziertronic/octant/issues/70) — ouvert le 2026-06-23 par @momsse._ ## Summary React **hydration mismatch** on the backoffice `/login` route: the server-rendered HTML does not match the client tree, so React discards and regenerates the subtree on the client. Observed in `apps/backoffice` running `pnpm dev` (Vite + TanStack Start SSR, React 19), when loading `http://localhost:3000/login`. ## Console error ``` Error: Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client. <DialogsProvider> <OutletImpl> <Suspense fallback={null}> <MatchImpl matchId="/(auth)/lo..."> <MatchView ...> ... <MatchInnerImpl matchId="/(auth)/lo..."> <Lazy> <LoginPage> + <main className="flex min-h-screen items-center justify-center"> - <Suspense> ``` The diff points at the `LoginPage` boundary: the client renders `<main>` while the server emitted a `<Suspense>` placeholder — i.e. the lazy route component is resolved on the client but was still suspended/fallback during SSR. ## Steps to reproduce 1. `pnpm --filter @octant/backoffice dev` 2. Open `http://localhost:3000/login` 3. Observe the hydration-mismatch exception in the browser console on first load. ## Suspected cause TanStack Start SSR renders the lazy-loaded route component inside a `<Suspense>` boundary; the server emits the fallback while the client resolves the real component, producing a structural mismatch on hydration. Likely affects other lazy routes too, not just `/login`. ## Scope / notes - Reproduced on the PR #65 (`split/13-backoffice`) branch. `routes/(auth)/login.tsx` and `routes/__root.tsx` are unchanged by recent review fixes, so this appears to be a scaffold-level SSR/lazy-route issue rather than a regression from those fixes. - The page still renders and works after the client regeneration, but the mismatch should be resolved to avoid the SSR penalty and console noise. ## Environment - `apps/backoffice` — TanStack Start (SSR), React 19, Vite 7 (`vite dev`)
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
momsse/octant#27
No description provided.