Skip to content

Conversation

@ali-idrizi
Copy link
Contributor

@ali-idrizi ali-idrizi commented Nov 29, 2025

fixes #5992

Summary by CodeRabbit

  • Bug Fixes
    • Fixed a server-side rendering issue where HTML content wasn't properly reset during stream processing, potentially causing rendering problems with routed content.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 29, 2025

Walkthrough

The change modifies the SSR stream transformation logic to reset the leftoverHtml buffer to an empty string after processing chunks containing closing tags, preventing leftoverHtml from accumulating across iterations and causing duplicate query dehydration in streamed responses.

Changes

Cohort / File(s) Summary
SSR Stream Leftover HTML Buffer Reset
packages/router-core/src/ssr/transformStreamWithRouter.ts
Adds logic to reset leftoverHtml to empty string immediately after writing chunks with closing tags (lastIndex > 0), preventing accumulation and duplicate query dehydration across subsequent stream iterations.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

  • Single file affected with a targeted variable-reset logic addition
  • Clear conditional change addressing a specific accumulation issue
  • Low complexity but critical impact on query dehydration during streaming

Possibly related PRs

  • fix: cleanup references #5965: Also modifies transformStreamWithRouter.ts and handles cleanup/buffer management in router SSR HTML injection logic
  • fix: memory leaks #5896: Modifies stream handling in the same SSR file, restructuring passthrough and injected-HTML listener lifecycle

Suggested labels

package: router-core

Suggested reviewers

  • schiller-manuel
  • birkskyum

Poem

🐰 A leftover feast no longer grows,
Each closing tag now clearly shows—
Reset the buffer, clear the slate,
Queries dehydrate just once, not eight! ✨
Stream flows smooth through Router's gate.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: clearing leftoverHtml after flushing closing tags to prevent repeated SSR injections, which directly addresses the issue of queries being dehydrated multiple times.
Linked Issues check ✅ Passed The code change directly addresses issue #5992 by resetting leftoverHtml after processing closing tags, preventing accumulation that caused repeated query dehydrations during streaming SSR.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing the leftoverHtml accumulation issue in the SSR streaming logic, with no unrelated modifications present.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between af02265 and fe2c308.

📒 Files selected for processing (1)
  • packages/router-core/src/ssr/transformStreamWithRouter.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript strict mode with extensive type safety throughout the codebase

Files:

  • packages/router-core/src/ssr/transformStreamWithRouter.ts
🧠 Learnings (4)
📚 Learning: 2025-11-25T00:18:21.282Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T00:18:21.282Z
Learning: Applies to packages/solid-router/**/*.{ts,tsx} : Solid Router components and primitives should use the tanstack/solid-router package

Applied to files:

  • packages/router-core/src/ssr/transformStreamWithRouter.ts
📚 Learning: 2025-10-08T08:11:47.088Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5402
File: packages/router-generator/tests/generator/no-formatted-route-tree/routeTree.nonnested.snapshot.ts:19-21
Timestamp: 2025-10-08T08:11:47.088Z
Learning: Test snapshot files in the router-generator tests directory (e.g., files matching the pattern `packages/router-generator/tests/generator/**/routeTree*.snapshot.ts` or `routeTree*.snapshot.js`) should not be modified or have issues flagged, as they are fixtures used to verify the generator's output and are intentionally preserved as-is.

Applied to files:

  • packages/router-core/src/ssr/transformStreamWithRouter.ts
📚 Learning: 2025-10-01T18:30:26.591Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 5330
File: packages/router-core/src/router.ts:2231-2245
Timestamp: 2025-10-01T18:30:26.591Z
Learning: In `packages/router-core/src/router.ts`, the `resolveRedirect` method intentionally strips the router's origin from redirect URLs when they match (e.g., `https://foo.com/bar` → `/bar` for same-origin redirects) while preserving the full URL for cross-origin redirects. This logic should not be removed or simplified to use `location.publicHref` directly.

Applied to files:

  • packages/router-core/src/ssr/transformStreamWithRouter.ts
📚 Learning: 2025-11-25T00:18:21.282Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T00:18:21.282Z
Learning: Applies to packages/react-router/**/*.{ts,tsx} : React Router components and hooks should use the tanstack/react-router package

Applied to files:

  • packages/router-core/src/ssr/transformStreamWithRouter.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Preview
  • GitHub Check: Test
🔇 Additional comments (3)
packages/router-core/src/ssr/transformStreamWithRouter.ts (3)

241-241: Critical fix for duplicate SSR injections looks correct.

This change directly addresses the bug reported in #5992. Previously, leftoverHtml was written at line 237 but never cleared, causing the same dehydrated query data to be injected multiple times when subsequent chunks contained closing tags. Resetting it here prevents accumulation across iterations and ensures each query is dehydrated exactly once.


227-245: Buffer management logic is now consistent across all branches.

The chunk processing correctly handles leftoverHtml in both branches:

  • When closing tags are found (lines 233-241): writes accumulated leftoverHtml and clears it
  • When no closing tags (lines 242-245): accumulates router stream data into leftoverHtml for the next iteration

This mirrors the pattern used by getBufferedRouterStream() and ensures proper cleanup. The final flush at line 176 correctly includes any remaining leftoverHtml.


211-225: Based on my analysis of the review comment provided, I can see that the scratchpad within the comment itself already contains thorough verification of the leftoverHtml handling behavior. The analysis concludes that while the code flow is subtle, it is correct and intentional.

The code properly preserves leftoverHtml through this flow:

  1. When body/html end is detected → early exit with partial write (lines 219-221) and leftover = '' (line 223)
  2. Later, onEnd is called → final flush (lines 172-178)
  3. Final flush writes: leftoverHtml + remaining data + closingTags

This ensures leftoverHtml content appears between the partial content write and the closing tags, which is the correct positioning.

The concern flagged in the review is not an actual bug—it's a subtle but correct implementation pattern. The verification in the existing scratchpad analysis confirms the intended behavior is working as designed.

The leftoverHtml handling is correct and requires no code changes.

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link

nx-cloud bot commented Nov 29, 2025

View your CI Pipeline Execution ↗ for commit fe2c308

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ✅ Succeeded 9m 7s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 1m 25s View ↗

☁️ Nx Cloud last updated this comment at 2025-11-29 12:27:21 UTC

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 29, 2025

More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/arktype-adapter@5993

@tanstack/directive-functions-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/directive-functions-plugin@5993

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/eslint-plugin-router@5993

@tanstack/history

npm i https://pkg.pr.new/TanStack/router/@tanstack/history@5993

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/nitro-v2-vite-plugin@5993

@tanstack/react-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router@5993

@tanstack/react-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-devtools@5993

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-ssr-query@5993

@tanstack/react-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start@5993

@tanstack/react-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-client@5993

@tanstack/react-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-server@5993

@tanstack/router-cli

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-cli@5993

@tanstack/router-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-core@5993

@tanstack/router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools@5993

@tanstack/router-devtools-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools-core@5993

@tanstack/router-generator

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-generator@5993

@tanstack/router-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-plugin@5993

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-ssr-query-core@5993

@tanstack/router-utils

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-utils@5993

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-vite-plugin@5993

@tanstack/server-functions-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/server-functions-plugin@5993

@tanstack/solid-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router@5993

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-devtools@5993

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-ssr-query@5993

@tanstack/solid-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start@5993

@tanstack/solid-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-client@5993

@tanstack/solid-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-server@5993

@tanstack/start-client-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-client-core@5993

@tanstack/start-plugin-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-plugin-core@5993

@tanstack/start-server-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-core@5993

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-static-server-functions@5993

@tanstack/start-storage-context

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-storage-context@5993

@tanstack/valibot-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/valibot-adapter@5993

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/TanStack/router/@tanstack/virtual-file-routes@5993

@tanstack/zod-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/zod-adapter@5993

commit: fe2c308

@ali-idrizi ali-idrizi closed this Nov 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Same query dehydrated many times when React flushes

1 participant