Skip to content

Bots get Suspense fallbacks instead of full HTML since 1.170.37 #8687

Open

Description

@GregoryCollett

Which project does this relate to?

Router

Describe the bug

Since 1.170.37 (#8204), bots get Suspense fallbacks instead of the full HTML.

renderRouterToStream creates the response stream before it awaits stream.allReady. That stream (makeMergeStream in transformStreamWithRouter.ts) has the default highWaterMark: 1, so it pulls from React as soon as it is created. React sends the shell early and streams the rest.

Reproduces on Node and on Cloudflare Workers.

Complete minimal reproducer

https://github.com/GregoryCollett/tanstack-start-bot-repro

Steps to Reproduce the Bug

  1. npm install && npm run build && npm start
  2. curl -A Googlebot http://localhost:3000/

Expected behavior

The response contains <p>slow content</p>, as it does on 1.170.36. On 1.170.42 it contains <p>loading</p> in a pending <!--$?--> boundary.

Platform

  • Router / Start Version: react-router 1.170.42, react-start 1.168.61
  • OS: macOS
  • Browser: n/a (curl with a bot user agent)
  • Bundler: vite
  • Bundler Version: 8.3.4

Additional context

Passing highWaterMark: 0 fixes it for us, and browsers still stream:

const stream = new ReadableStream<Uint8Array>(
  { start, pull, cancel },
  { highWaterMark: 0 },
)

Activity

  1. GregoryCollett commented on Oct 12, 2026

    @GregoryCollett
    ContributorAuthor

    This can effect SEO for any Start app that uses Suspense. Crawlers could now index the loading fallbacks rather than the page content (dependent on the crawler/bot in question).

    Happy to open a PR with the highWaterMark: 0 change and a test if thats useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions