T
TanStack2mo ago
absent-sapphire

[RESOLVED] Hydration Issue with Clerk, TSS, & Convex

Morning team, I thought this issue would have been resolved upgrading to the new main branch, but seeing this hydration issue with Clerk, TSS, and Convex. Any thoughts on how I can resolve this?
A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:

- A server/client branch `if (typeof window !== 'undefined')`.
- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.
- Date formatting in a user's locale which doesn't match the server.
- External changing data without sending a snapshot of it along with the HTML.
- Invalid HTML tag nesting.

It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.

https://react.dev/link/hydration-mismatch

...
<OrganizationProvider organization={undefined}>
<SWRConfig value={undefined}>
<ConvexProviderWithClerk client={{address:"h...", ...}} useAuth={function useAuth}>
<ConvexProviderWithAuth client={{address:"h...", ...}} useAuth={function useAuthFromClerk}>
<ConvexAuthStateFirstEffect>
<ConvexProvider client={{address:"h...", ...}}>
<RootDocument>
<html
lang="en"
- className="light"
- style={{color-scheme:"light"}}
>
...
A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:

- A server/client branch `if (typeof window !== 'undefined')`.
- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.
- Date formatting in a user's locale which doesn't match the server.
- External changing data without sending a snapshot of it along with the HTML.
- Invalid HTML tag nesting.

It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.

https://react.dev/link/hydration-mismatch

...
<OrganizationProvider organization={undefined}>
<SWRConfig value={undefined}>
<ConvexProviderWithClerk client={{address:"h...", ...}} useAuth={function useAuth}>
<ConvexProviderWithAuth client={{address:"h...", ...}} useAuth={function useAuthFromClerk}>
<ConvexAuthStateFirstEffect>
<ConvexProvider client={{address:"h...", ...}}>
<RootDocument>
<html
lang="en"
- className="light"
- style={{color-scheme:"light"}}
>
...
8 Replies
absent-sapphire
absent-sapphireOP2mo ago
Looks like it might be related to a 307 I'm getting on app load:
[vite] connected.
Fetching Clerk auth...
Fetching Clerk auth...
Error fetching Clerk auth: Response {
status: 307,
statusText: '',
headers: Headers {
location: '<REDACTED>.clerk.accounts.dev/v1/client/handshake?redirect_url=<REDACTED>__clerk_api_version=2025-04-10&suffixed_cookies=false&__clerk_hs_reason=dev-browser-missing&format=nonce',
'cache-control': 'no-store',
'Set-Cookie': '__clerk_redirect_count=1; SameSite=Lax; HttpOnly; Max-Age=3',
'x-clerk-auth-reason': 'dev-browser-missing',
'x-clerk-auth-status': 'handshake'
},
body: null,
bodyUsed: false,
ok: false,
redirected: false,
type: 'default',
url: ''
}
Fetching Clerk auth...
Fetching Clerk auth...
Fetching Clerk auth...
[vite] connected.
Fetching Clerk auth...
Fetching Clerk auth...
Error fetching Clerk auth: Response {
status: 307,
statusText: '',
headers: Headers {
location: '<REDACTED>.clerk.accounts.dev/v1/client/handshake?redirect_url=<REDACTED>__clerk_api_version=2025-04-10&suffixed_cookies=false&__clerk_hs_reason=dev-browser-missing&format=nonce',
'cache-control': 'no-store',
'Set-Cookie': '__clerk_redirect_count=1; SameSite=Lax; HttpOnly; Max-Age=3',
'x-clerk-auth-reason': 'dev-browser-missing',
'x-clerk-auth-status': 'handshake'
},
body: null,
bodyUsed: false,
ok: false,
redirected: false,
type: 'default',
url: ''
}
Fetching Clerk auth...
Fetching Clerk auth...
Fetching Clerk auth...
SW Versions: "@clerk/tanstack-react-start": "0.18.0", "@tanstack/react-router": "^1.121.34", "@tanstack/react-router-devtools": "^1.121.34", "@tanstack/react-start": "^1.121.35", Code:
import { ClerkProvider, useAuth } from "@clerk/tanstack-react-start";


function RootComponent() {
const context = useRouteContext({ from: Route.id });

return (
<ClerkProvider publishableKey={import.meta.env.VITE_CLERK_PUBLISHABLE_KEY}>
<ConvexProviderWithClerk client={context.convexClient} useAuth={useAuth}>
<RootDocument>
<Outlet />
</RootDocument>
</ConvexProviderWithClerk>
</ClerkProvider>
);
}

function RootDocument({ children }: { children: React.ReactNode }) {
const location = useLocation();
const isIndexPage = location.pathname === "/";

return (
<html lang="en">
<head>
<HeadContent />
</head>
<body>
<ThemeProvider
attribute="class"
defaultTheme="light"
enableSystem={!isIndexPage}
forcedTheme={isIndexPage ? "light" : undefined}
>
<main>{children}</main>
</ThemeProvider>
<TanStackRouterDevtools position="bottom-left" />
<Scripts />
</body>
</html>
);
}
import { ClerkProvider, useAuth } from "@clerk/tanstack-react-start";


function RootComponent() {
const context = useRouteContext({ from: Route.id });

return (
<ClerkProvider publishableKey={import.meta.env.VITE_CLERK_PUBLISHABLE_KEY}>
<ConvexProviderWithClerk client={context.convexClient} useAuth={useAuth}>
<RootDocument>
<Outlet />
</RootDocument>
</ConvexProviderWithClerk>
</ClerkProvider>
);
}

function RootDocument({ children }: { children: React.ReactNode }) {
const location = useLocation();
const isIndexPage = location.pathname === "/";

return (
<html lang="en">
<head>
<HeadContent />
</head>
<body>
<ThemeProvider
attribute="class"
defaultTheme="light"
enableSystem={!isIndexPage}
forcedTheme={isIndexPage ? "light" : undefined}
>
<main>{children}</main>
</ThemeProvider>
<TanStackRouterDevtools position="bottom-left" />
<Scripts />
</body>
</html>
);
}
noble-gold
noble-gold2mo ago
is isIndexPage different on client and server?
absent-sapphire
absent-sapphireOP2mo ago
shouldn't be?
const location = useLocation();
const isIndexPage = location.pathname === "/";
const location = useLocation();
const isIndexPage = location.pathname === "/";
noble-gold
noble-gold2mo ago
but your hydration diff seems to be affected by the theme?
<html
lang="en"
- className="light"
- style={{color-scheme:"light"}}

<html
lang="en"
- className="light"
- style={{color-scheme:"light"}}

absent-sapphire
absent-sapphireOP2mo ago
oh yup you're totally right, theme provider is def causing it maybe this is an artifact from when I was on just router... do y'all have a standard theme provider now for start in any of the templates?
noble-gold
noble-gold2mo ago
not yet
absent-sapphire
absent-sapphireOP2mo ago
Ahh, I looked back on a gist I found before and I was missing supressing the hydration warning it seems.
absent-sapphire
absent-sapphireOP2mo ago
for y'alls record, here's the gist I was using, functionally works but yea good shout on pointing out this was the root cause. https://gist.github.com/WellDone2094/16107a2a9476b28a5b394bee3fa1b8a3
Gist
Tan Stack Start Theme provider
Tan Stack Start Theme provider. GitHub Gist: instantly share code, notes, and snippets.

Did you find this page helpful?