Which project does this relate to?
Router
Describe the bug
Disclaimer: I'm relatively new to TanStack Start/Router and it's possible I'm missing a configuration option that addresses this. If so, I'd appreciate being pointed in the right direction. I did search existing issues and docs before filing.
TanStack Router constructs match IDs by concatenating route.id + interpolatedPath + loaderDepsHash (router.ts:1630). These match IDs are then serialized into SSR HTML via dehydrateMatch() (ssr-server.ts:40) and injected into inline <script> tags through crossSerializeStream.
The resulting match IDs look like relative URLs. For example, a route src/routes/$orgId/projects/$projectId/index.tsx visited at /acme/projects/dashboard produces:
/$orgId/projects/$projectId//acme/projects/dashboard/{}
Google's crawler parses the full SSR HTML source — including <script> content — extracts these path-like strings, and attempts to crawl them. This produces phantom entries in Google Search Console reported as "Redirect Error" or "Not Found (404)".
This is the same class of issue as Next.js's __NEXT_DATA__ problem (vercel/next.js#39377, vercel/next.js#40143).
Your Example Website or App
https://stackblitz.com/edit/github-4qzy4wjc?file=src%2Froutes%2Fabout.tsx
Steps to Reproduce the Bug or Issue
- Create a TanStack Start app with a dynamic route (e.g.,
src/routes/$orgId/projects/$projectId/index.tsx)
- Start the dev server
- Visit a page that resolves the route (e.g.,
/acme/projects/dashboard)
- View the HTML source
- Search for
$_TSR in the source — the dehydrated <script> tags contain match IDs like:
/$orgId/projects/$projectId//acme/projects/dashboard/
This string starts with /, contains path separators, and is indistinguishable from a relative URL.
Expected behavior
Match IDs serialized into SSR HTML should not be extractable by crawlers as valid URLs. They are internal router identifiers and ideally they use a format that cannot be mistaken for relative URL paths.
Screenshots or Videos
No response
Platform
- Router / Start Version: 1.157.18
- OS: Windows
- Browser: Chrome
- Browser Version: 133
- Bundler: vite
- Bundler Version: 7.3.1
Additional context
The match ID at router.ts:1630 is a simple string concatenation:
const matchId =
route.id + // "/$orgId/projects/$projectId/" (route pattern)
interpolatedPath + // "/acme/projects/dashboard/" (resolved path)
loaderDepsHash // "{}" (JSON.stringify of deps)
Result: /$orgId/projects/$projectId//acme/projects/dashboard/{} — a string that:
- Starts with
/ (relative URL)
- Contains valid path separators throughout
- Is serialized as a plain string property
i: match.id in dehydrateMatch()
- Is injected as-is into inline
<script> tags via crossSerializeStream from seroval
Google's crawler is known to extract path-like strings from HTML source — including inline script content — and attempt to fetch them.
Which project does this relate to?
Router
Describe the bug
TanStack Router constructs match IDs by concatenating
route.id + interpolatedPath + loaderDepsHash(router.ts:1630). These match IDs are then serialized into SSR HTML viadehydrateMatch()(ssr-server.ts:40) and injected into inline<script>tags throughcrossSerializeStream.The resulting match IDs look like relative URLs. For example, a route
src/routes/$orgId/projects/$projectId/index.tsxvisited at/acme/projects/dashboardproduces:Google's crawler parses the full SSR HTML source — including
<script>content — extracts these path-like strings, and attempts to crawl them. This produces phantom entries in Google Search Console reported as "Redirect Error" or "Not Found (404)".This is the same class of issue as Next.js's
__NEXT_DATA__problem (vercel/next.js#39377, vercel/next.js#40143).Your Example Website or App
https://stackblitz.com/edit/github-4qzy4wjc?file=src%2Froutes%2Fabout.tsx
Steps to Reproduce the Bug or Issue
src/routes/$orgId/projects/$projectId/index.tsx)/acme/projects/dashboard)$_TSRin the source — the dehydrated<script>tags contain match IDs like:/, contains path separators, and is indistinguishable from a relative URL.Expected behavior
Match IDs serialized into SSR HTML should not be extractable by crawlers as valid URLs. They are internal router identifiers and ideally they use a format that cannot be mistaken for relative URL paths.
Screenshots or Videos
No response
Platform
Additional context
The match ID at
router.ts:1630is a simple string concatenation:Result:
/$orgId/projects/$projectId//acme/projects/dashboard/{}— a string that:/(relative URL)i: match.idindehydrateMatch()<script>tags viacrossSerializeStreamfrom serovalGoogle's crawler is known to extract path-like strings from HTML source — including inline script content — and attempt to fetch them.