A TanStack Start hydration error means the first browser render differs from the server HTML. Start by checking dates, locale and timezone formatting, random ids, responsive logic, and saved preferences. TanStack's hydration guide covers these causes too.
Common hydration errors in TanStack Start
TanStack Start shows React's hydration messages. With React 19, you may see:
Hydration failed because the server rendered HTML didn't match the client. As a result this tree will be regenerated on the client.
A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up.A TanStack Start hydration mismatch usually fits one of these cases:
| Cause | Typical code | Fix |
|---|---|---|
| Locale and time zone | Intl.DateTimeFormat(), toLocaleString() without an explicit locale or timeZone | Locale, timezone |
| The clock | Date.now(), new Date() in a component | Time |
| Random values | random ids, Math.random() in render | Random values |
| Screen size | responsive logic that reads window or matchMedia | Media queries |
| User preferences | theme or flags read from the browser | Theme, browser APIs |
How to fix a TanStack Start hydration error
Choose the fix that preserves server-rendered content when possible. Use client-only rendering when the component truly needs the browser.
Make the server and the client agree
Choose a locale and timezone on the server and pass them to the client. A
cookie can store a known preference; Accept-Language can be a fallback for
locale. If the server does not know the browser's timezone yet, use a stable
timezone such as UTC for the first render.
Let the client report its environment
On a first visit, read the browser's timezone after hydration and save it in a cookie. The server can use it on later requests.
Render unstable UI on the client only
Use ClientOnly from @tanstack/react-router for content that cannot render
on the server. It shows a fallback until hydration finishes:
import { ClientOnly } from "@tanstack/react-router";
import { RelativeTime } from "./relative-time";
export function LastSeen({ ts }: { ts: number }) {
return (
<ClientOnly fallback={<span>—</span>}>
<RelativeTime ts={ts} />
</ClientOnly>
);
}Turn off server rendering for a route
TanStack Start can server-render only a route's data with ssr: "data-only",
or skip server rendering for that route with ssr: false:
import { createFileRoute } from "@tanstack/react-router";
import { ExpensiveViz } from "../components/expensive-viz";
export const Route = createFileRoute("/unstable")({
ssr: "data-only",
component: ExpensiveViz,
});Suppress the warning as a last resort
If one element must differ, suppressHydrationWarning can hide its warning.
It does not fix the difference. See when it is safe.
Test every route with hydration-proof
There is no built-in TanStack Start adapter. Provide the app URL and routes, or configure the build and start commands. You can also write an adapter.
Test an app you started
Start the app, then point hydration-proof at its URL and name the routes:
npx hydration-proof test --url http://localhost:3000 --route / --route /postsWith --url, hydration-proof does not build or start the app. Add --sitemap
to include sitemap pages, or --crawl to follow links.
Let hydration-proof build and start it
Use adapter: "none" and give it your commands:
import { defineConfig } from "hydration-proof";
export default defineConfig({
adapter: "none",
server: {
build: "npm run build",
command: "npm run start", // must listen on process.env.PORT
},
routes: { paths: ["/", "/posts", "/posts/1"] },
});hydration-proof picks a free port and passes it as PORT. It also replaces
{port} in a command. Without an adapter, server.build runs on every check.
Set server.buildWhen: "never" if CI already built the app.
Run npx hydration-proof doctor to see what adapter: "auto" detects. A
generic Node adapter may use your build, start, and dev scripts, but you
still need to provide routes.
Write an adapter
If you want automatic route discovery, write an adapter with defineAdapter.
See writing an adapter
for the required pieces.