Skip to content

response reconciliation#7588

Open
schiller-manuel wants to merge 1 commit into
mainfrom
response-reconciliation
Open

response reconciliation#7588
schiller-manuel wants to merge 1 commit into
mainfrom
response-reconciliation

Conversation

@schiller-manuel

@schiller-manuel schiller-manuel commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

fixes #5107
fixes #5464
fixes #5407

Summary by CodeRabbit

  • New Features

    • Improved response reconciliation across server routes, SSR, and server functions (cookies, headers, status).
    • Enhanced session handling and cookie helpers for robust persistence and recovery.
    • Added default error/catch UI and route utilities for E2E apps.
  • Bug Fixes

    • Safer server-entry error recovery and protected header handling to avoid overwrites.
    • Fixed middleware/response ordering and multi-cookie preservation across redirects/replacements.
  • Documentation

    • Updated server entry guide and added reconciliation docs.
  • Tests

    • New comprehensive E2E and unit tests covering reconciliation and session behavior.

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 83e61506-682d-4aeb-b86c-aef7852a71fe

📥 Commits

Reviewing files that changed from the base of the PR and between fe11405 and 97e14ca.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (86)
  • .changeset/start-response-state.md
  • docs/start/framework/react/guide/server-entry-point.md
  • e2e/react-start/response-reconciliation/.gitignore
  • e2e/react-start/response-reconciliation/.prettierignore
  • e2e/react-start/response-reconciliation/package.json
  • e2e/react-start/response-reconciliation/playwright.config.ts
  • e2e/react-start/response-reconciliation/rsbuild.config.ts
  • e2e/react-start/response-reconciliation/server.js
  • e2e/react-start/response-reconciliation/src/components/DefaultCatchBoundary.tsx
  • e2e/react-start/response-reconciliation/src/components/NotFound.tsx
  • e2e/react-start/response-reconciliation/src/routeTree.gen.ts
  • e2e/react-start/response-reconciliation/src/router.tsx
  • e2e/react-start/response-reconciliation/src/routes/__root.tsx
  • e2e/react-start/response-reconciliation/src/routes/api/-response.ts
  • e2e/react-start/response-reconciliation/src/routes/api/base.ts
  • e2e/react-start/response-reconciliation/src/routes/api/bulk-headers.ts
  • e2e/react-start/response-reconciliation/src/routes/api/clear-returned-headers.ts
  • e2e/react-start/response-reconciliation/src/routes/api/direct-mutation-visible.ts
  • e2e/react-start/response-reconciliation/src/routes/api/explicit-set-cookie-header.ts
  • e2e/react-start/response-reconciliation/src/routes/api/get-response-header-helper.ts
  • e2e/react-start/response-reconciliation/src/routes/api/get-response-headers-helper.ts
  • e2e/react-start/response-reconciliation/src/routes/api/multiple-cookies.ts
  • e2e/react-start/response-reconciliation/src/routes/api/null-body-status.ts
  • e2e/react-start/response-reconciliation/src/routes/api/readonly-after-next.ts
  • e2e/react-start/response-reconciliation/src/routes/api/redirect-with-cookies.ts
  • e2e/react-start/response-reconciliation/src/routes/api/remove-returned-header.ts
  • e2e/react-start/response-reconciliation/src/routes/api/replace-after-direct-mutation.ts
  • e2e/react-start/response-reconciliation/src/routes/api/replace-explicit-set-cookie.ts
  • e2e/react-start/response-reconciliation/src/routes/api/route-after-next.ts
  • e2e/react-start/response-reconciliation/src/routes/api/route-before-next.ts
  • e2e/react-start/response-reconciliation/src/routes/api/same-boundary-conflict.ts
  • e2e/react-start/response-reconciliation/src/routes/api/throw-after-status.ts
  • e2e/react-start/response-reconciliation/src/routes/api/two-returned-responses.ts
  • e2e/react-start/response-reconciliation/src/routes/index.tsx
  • e2e/react-start/response-reconciliation/src/routes/server-functions.tsx
  • e2e/react-start/response-reconciliation/src/routes/ssr.tsx
  • e2e/react-start/response-reconciliation/src/server-entry.ts
  • e2e/react-start/response-reconciliation/src/start.ts
  • e2e/react-start/response-reconciliation/src/styles/app.css
  • e2e/react-start/response-reconciliation/tests/response-reconciliation.spec.ts
  • e2e/react-start/response-reconciliation/tsconfig.json
  • e2e/react-start/response-reconciliation/vite.config.ts
  • e2e/react-start/session-handling/.gitignore
  • e2e/react-start/session-handling/.prettierignore
  • e2e/react-start/session-handling/package.json
  • e2e/react-start/session-handling/playwright.config.ts
  • e2e/react-start/session-handling/rsbuild.config.ts
  • e2e/react-start/session-handling/server.js
  • e2e/react-start/session-handling/src/components/DefaultCatchBoundary.tsx
  • e2e/react-start/session-handling/src/components/NotFound.tsx
  • e2e/react-start/session-handling/src/routeTree.gen.ts
  • e2e/react-start/session-handling/src/router.tsx
  • e2e/react-start/session-handling/src/routes/__root.tsx
  • e2e/react-start/session-handling/src/routes/api/session-clear.ts
  • e2e/react-start/session-handling/src/routes/api/session-cookie-disabled.ts
  • e2e/react-start/session-handling/src/routes/api/session-header.ts
  • e2e/react-start/session-handling/src/routes/api/session-helper-cookie.ts
  • e2e/react-start/session-handling/src/routes/api/session-middleware.ts
  • e2e/react-start/session-handling/src/routes/api/session-named.ts
  • e2e/react-start/session-handling/src/routes/api/session-seal.ts
  • e2e/react-start/session-handling/src/routes/api/session.ts
  • e2e/react-start/session-handling/src/routes/index.tsx
  • e2e/react-start/session-handling/src/routes/server-functions.tsx
  • e2e/react-start/session-handling/src/routes/ssr.tsx
  • e2e/react-start/session-handling/src/session.ts
  • e2e/react-start/session-handling/src/start.ts
  • e2e/react-start/session-handling/src/styles/app.css
  • e2e/react-start/session-handling/tests/session-handling.spec.ts
  • e2e/react-start/session-handling/tsconfig.json
  • e2e/react-start/session-handling/vite.config.ts
  • packages/react-start/src/default-entry/server.ts
  • packages/solid-start/src/default-entry/server.ts
  • packages/start-plugin-core/src/vite/plugin.ts
  • packages/start-plugin-core/tests/entry-planning.test.ts
  • packages/start-server-core/docs/RECONCILIATION.md
  • packages/start-server-core/package.json
  • packages/start-server-core/skills/start-server-core/SKILL.md
  • packages/start-server-core/src/createStartHandler.ts
  • packages/start-server-core/src/headers.ts
  • packages/start-server-core/src/internal-request-response.ts
  • packages/start-server-core/src/request-response.ts
  • packages/start-server-core/src/server-functions-handler.ts
  • packages/start-server-core/tests/createStartHandler.test.ts
  • packages/start-server-core/tests/server-functions-handler.test.ts
  • packages/start-server-core/vite.config.ts
  • packages/vue-start/src/default-entry/server.ts
✅ Files skipped from review due to trivial changes (15)
  • e2e/react-start/session-handling/src/styles/app.css
  • e2e/react-start/response-reconciliation/src/routes/api/two-returned-responses.ts
  • e2e/react-start/response-reconciliation/src/routes/api/route-after-next.ts
  • e2e/react-start/response-reconciliation/tsconfig.json
  • e2e/react-start/session-handling/.prettierignore
  • packages/start-plugin-core/src/vite/plugin.ts
  • e2e/react-start/session-handling/package.json
  • e2e/react-start/response-reconciliation/src/styles/app.css
  • e2e/react-start/response-reconciliation/.prettierignore
  • .changeset/start-response-state.md
  • e2e/react-start/response-reconciliation/.gitignore
  • e2e/react-start/session-handling/.gitignore
  • packages/start-server-core/skills/start-server-core/SKILL.md
  • e2e/react-start/response-reconciliation/package.json
  • e2e/react-start/response-reconciliation/src/routeTree.gen.ts
🚧 Files skipped from review as they are similar to previous changes (63)
  • e2e/react-start/session-handling/src/routes/api/session.ts
  • e2e/react-start/session-handling/src/routes/index.tsx
  • e2e/react-start/response-reconciliation/src/routes/api/direct-mutation-visible.ts
  • packages/vue-start/src/default-entry/server.ts
  • e2e/react-start/session-handling/src/routes/api/session-cookie-disabled.ts
  • e2e/react-start/session-handling/src/components/DefaultCatchBoundary.tsx
  • e2e/react-start/session-handling/vite.config.ts
  • e2e/react-start/response-reconciliation/src/routes/api/readonly-after-next.ts
  • e2e/react-start/response-reconciliation/src/components/DefaultCatchBoundary.tsx
  • e2e/react-start/response-reconciliation/src/routes/api/null-body-status.ts
  • packages/start-server-core/vite.config.ts
  • e2e/react-start/response-reconciliation/src/components/NotFound.tsx
  • e2e/react-start/response-reconciliation/vite.config.ts
  • e2e/react-start/response-reconciliation/src/router.tsx
  • e2e/react-start/response-reconciliation/src/routes/api/clear-returned-headers.ts
  • packages/react-start/src/default-entry/server.ts
  • e2e/react-start/response-reconciliation/src/routes/api/multiple-cookies.ts
  • e2e/react-start/response-reconciliation/src/routes/api/route-before-next.ts
  • e2e/react-start/response-reconciliation/src/routes/api/explicit-set-cookie-header.ts
  • e2e/react-start/session-handling/src/routes/api/session-seal.ts
  • e2e/react-start/response-reconciliation/src/routes/api/replace-after-direct-mutation.ts
  • e2e/react-start/session-handling/src/routes/api/session-header.ts
  • e2e/react-start/session-handling/src/router.tsx
  • e2e/react-start/response-reconciliation/src/routes/index.tsx
  • packages/solid-start/src/default-entry/server.ts
  • e2e/react-start/session-handling/src/routes/api/session-helper-cookie.ts
  • e2e/react-start/session-handling/src/routes/api/session-clear.ts
  • e2e/react-start/session-handling/src/routes/__root.tsx
  • e2e/react-start/session-handling/server.js
  • e2e/react-start/response-reconciliation/src/routes/api/get-response-header-helper.ts
  • packages/start-plugin-core/tests/entry-planning.test.ts
  • e2e/react-start/response-reconciliation/src/start.ts
  • e2e/react-start/session-handling/src/components/NotFound.tsx
  • e2e/react-start/response-reconciliation/rsbuild.config.ts
  • e2e/react-start/response-reconciliation/src/routes/api/remove-returned-header.ts
  • e2e/react-start/response-reconciliation/src/routes/__root.tsx
  • e2e/react-start/response-reconciliation/src/routes/api/base.ts
  • e2e/react-start/response-reconciliation/src/routes/api/same-boundary-conflict.ts
  • e2e/react-start/session-handling/src/routeTree.gen.ts
  • e2e/react-start/session-handling/tsconfig.json
  • e2e/react-start/session-handling/playwright.config.ts
  • e2e/react-start/response-reconciliation/src/server-entry.ts
  • packages/start-server-core/src/request-response.ts
  • e2e/react-start/response-reconciliation/src/routes/api/-response.ts
  • e2e/react-start/response-reconciliation/src/routes/server-functions.tsx
  • e2e/react-start/response-reconciliation/server.js
  • e2e/react-start/session-handling/rsbuild.config.ts
  • e2e/react-start/response-reconciliation/src/routes/api/get-response-headers-helper.ts
  • packages/start-server-core/src/headers.ts
  • docs/start/framework/react/guide/server-entry-point.md
  • e2e/react-start/session-handling/src/session.ts
  • e2e/react-start/session-handling/src/routes/ssr.tsx
  • packages/start-server-core/tests/createStartHandler.test.ts
  • e2e/react-start/session-handling/tests/session-handling.spec.ts
  • e2e/react-start/session-handling/src/start.ts
  • e2e/react-start/response-reconciliation/src/routes/ssr.tsx
  • e2e/react-start/session-handling/src/routes/server-functions.tsx
  • e2e/react-start/session-handling/src/routes/api/session-named.ts
  • e2e/react-start/response-reconciliation/playwright.config.ts
  • packages/start-server-core/tests/server-functions-handler.test.ts
  • packages/start-server-core/src/server-functions-handler.ts
  • packages/start-server-core/src/internal-request-response.ts
  • packages/start-server-core/src/createStartHandler.ts

📝 Walkthrough

Walkthrough

Updates Start runtime request/response reconciliation, server-function framing/error handling, server-entry error recovery, documentation, and adds two React E2E workspaces with Playwright tests covering response reconciliation and session handling.

Changes

Start runtime and E2E validation

Layer / File(s) Summary
Runtime reconciliation, headers, cookies, sessions
packages/start-server-core/src/..., packages/start-server-core/package.json, packages/start-server-core/vite.config.ts
Reimplement request/response state around AsyncLocalStorage, add header utilities, set-cookie parsing/merge semantics, response reconciliation helpers, session bridge to H3, and re-export surface changes.
Server-function framing and error serialization
packages/start-server-core/src/server-functions-handler.ts, packages/start-server-core/tests/*
Refactor server-function payload parsing, framed streaming serialization, protected serialized headers, and createServerFnErrorResponse plus tests for errors/streaming.
Start handler, middleware, redirects, and wrappers
packages/start-server-core/src/createStartHandler.ts, packages/react-start/src/default-entry/server.ts, packages/solid-start/src/default-entry/server.ts, packages/vue-start/src/default-entry/server.ts
Rewrite middleware execution, reconcile responses (including SSR stream ownership), centralize redirect serialization, and wrap framework server entries to route uncaught errors through handleStartError.
Docs, release metadata, and entry planning
docs/start/framework/react/guide/server-entry-point.md, packages/start-server-core/docs/RECONCILIATION.md, packages/start-server-core/skills/start-server-core/SKILL.md, packages/start-plugin-core/tests/entry-planning.test.ts, .changeset/start-response-state.md
Update server-entry docs to preserve opts/context, add reconciliation documentation, adjust skill docs, and add entry-planning tests and changeset metadata.
Response reconciliation E2E app & tests
e2e/react-start/response-reconciliation/*
New E2E workspace exercising middleware, route handlers, SSR loaders, server functions, redirects, and custom server-entry error handling; includes Playwright config, rsbuild/vite configs, and tests asserting reconciliation semantics for headers/status/cookies.
Session handling E2E app & tests
e2e/react-start/session-handling/*
New E2E workspace exercising cookie-backed and header-based sessions, middleware timing, SSR persistence, server-function session access, Playwright tests, and helper utilities.

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant ServerEntry
  participant StartHandler
  participant Middleware
  participant ServerFn

  Browser->>ServerEntry: HTTP request (headers/cookies)
  ServerEntry->>StartHandler: fetch(request, opts)
  StartHandler->>Middleware: run request middleware (before/after)
  Middleware-->>StartHandler: mutate StartEvent (status/headers/cookies)
  StartHandler->>ServerFn: invoke server-function (if applicable)
  ServerFn-->>StartHandler: serialized result or framed stream / error
  StartHandler->>StartHandler: reconcile helper-driven state with returned Response
  StartHandler-->>ServerEntry: final Response (status, headers, Set-Cookie, body)
  ServerEntry-->>Browser: send response
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Suggested reviewers

  • Sheraff
  • beaussan
  • SeanCassiere

🐰 I hopped through headers, cookies, and streams,
and patched the paths where reconciliation gleams.
When errors now fall, they land tidy and clear,
cookies and status keep the order we cheer.
Hop hop — the rabbit says: tests are here!

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch response-reconciliation

@nx-cloud

nx-cloud Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

View your CI Pipeline Execution ↗ for commit 97e14ca

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ❌ Failed 9m 52s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 2m 13s View ↗

💡 Dealing with memory or CPU issues? See memory and CPU details with the resource usage add-on ↗.


☁️ Nx Cloud last updated this comment at 2026-06-08 22:26:06 UTC

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (8)
e2e/react-start/session-handling/src/session.ts (3)

23-31: ⚡ Quick win

Replace Record<string, any> with Record<string, unknown> for strict type safety.

Line 24 uses Record<string, any> which violates the TypeScript strict mode guideline.

♻️ Suggested fix
 export async function readSession(overrides: Record<string, unknown> = {}) {
-  const session = await useSession<Record<string, any>>(
+  const session = await useSession<Record<string, unknown>>(
     sessionConfig(overrides),
   )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/react-start/session-handling/src/session.ts` around lines 23 - 31, In
readSession, replace the loose generic Record<string, any> passed to useSession
with Record<string, unknown> to conform to strict TypeScript; update the
useSession<Record<string, unknown>>(...) type argument and ensure any downstream
accesses to session.data or session.id are typed/guarded appropriately (function
names: readSession and useSession, identifier: session.data/session.id).

Source: Coding guidelines


15-21: 💤 Low value

Consider logging or rethrowing JSON parsing errors.

Line 18 silently catches all errors and returns an empty object. While this provides resilience for E2E tests, it could mask malformed JSON or other issues during debugging.

💡 Optional improvement
 export async function readJson(request: Request) {
   try {
     return (await request.json()) as Record<string, unknown>
   } catch {
+    console.warn('Failed to parse request JSON, returning empty object')
     return {}
   }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/react-start/session-handling/src/session.ts` around lines 15 - 21, The
readJson function currently swallows all JSON parse errors and returns {}
silently; modify readJson to catch the error as a variable (e.g., catch (err))
and either log the error details (using console.error or the project logger)
before returning {} or rethrow the error so callers can handle it; optionally
add a boolean parameter like suppressErrors (default true) to preserve current
behavior in tests while allowing callers to surface errors when needed.

33-45: ⚡ Quick win

Replace Record<string, any> with Record<string, unknown> for strict type safety.

Line 37 uses Record<string, any> which violates the TypeScript strict mode guideline.

♻️ Suggested fix
 export async function updateSessionData(
   update: Record<string, unknown>,
   overrides: Record<string, unknown> = {},
 ) {
-  const session = await useSession<Record<string, any>>(
+  const session = await useSession<Record<string, unknown>>(
     sessionConfig(overrides),
   )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/react-start/session-handling/src/session.ts` around lines 33 - 45, The
function updateSessionData uses useSession with an explicit type Record<string,
any> which breaks strict TypeScript rules; change that generic to Record<string,
unknown> so the call becomes useSession<Record<string,
unknown>>(sessionConfig(overrides)), ensure any local references to session.data
or returned types are compatible with unknown (e.g., keep them typed as unknown
instead of any) and run type checks to fix any resulting type errors in
updateSessionData, useSession, or sessionConfig.

Source: Coding guidelines

e2e/react-start/session-handling/src/routes/server-functions.tsx (3)

16-22: ⚡ Quick win

Replace Record<string, any> with Record<string, unknown> for strict type safety.

Line 17 uses Record<string, any> which violates the TypeScript strict mode guideline.

♻️ Suggested fix
 const readSessionFn = createServerFn().handler(async () => {
-  const session = await useSession<Record<string, any>>(sessionConfig())
+  const session = await useSession<Record<string, unknown>>(sessionConfig())
   return {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/react-start/session-handling/src/routes/server-functions.tsx` around
lines 16 - 22, In readSessionFn replace the loose generic Record<string, any>
passed to useSession with Record<string, unknown> to satisfy strict TypeScript
rules; update any downstream usages in the handler that assume mutable or
specific typed values from session.data to use type-safe access or narrow/cast
as needed (refer to readSessionFn, useSession, and sessionConfig to locate the
call).

Source: Coding guidelines


7-14: ⚡ Quick win

Replace Record<string, any> with Record<string, unknown> for strict type safety.

Line 8 uses Record<string, any> which violates the TypeScript strict mode guideline. Consider using unknown instead of any to maintain type safety while preserving flexibility in this E2E test.

♻️ Suggested fix
 const updateSessionFn = createServerFn().handler(async () => {
-  const session = await useSession<Record<string, any>>(sessionConfig())
+  const session = await useSession<Record<string, unknown>>(sessionConfig())
   await session.update({ serverFn: 'updated' })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/react-start/session-handling/src/routes/server-functions.tsx` around
lines 7 - 14, Change the session generic from Record<string, any> to
Record<string, unknown> in the updateSessionFn handler: locate the
createServerFn().handler block where useSession<Record<string,
any>>(sessionConfig()) is called and update the generic to use Record<string,
unknown> (affecting updateSessionFn and its use of useSession/sessionConfig) to
enforce strict TypeScript safety without losing flexibility.

Source: Coding guidelines


41-70: ⚡ Quick win

Replace any types with stricter alternatives for type safety.

Line 46 uses any for function parameters and return type, which violates the TypeScript strict mode guideline.

♻️ Suggested fix
 function ServerFunctionButton({
   name,
   fn,
 }: {
   name: string
-  fn: (...args: Array<any>) => Promise<any>
+  fn: () => Promise<{ id: string; data: Record<string, unknown> }>
 }) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/react-start/session-handling/src/routes/server-functions.tsx` around
lines 41 - 70, The parameter types using any are too loose; change the fn prop
type from (...args: Array<any>) => Promise<any> to (...args: unknown[]) =>
Promise<unknown> (or an appropriate specific generic) and update the useServerFn
invocation to pass/declare that same generic so TypeScript infers safer types
for serverFn (e.g., useServerFn<typeof fn> or useServerFn<(...args: unknown[])
=> Promise<unknown>>(fn)); also update any local uses/annotations that relied on
any (for example ensure result state remains a string but document/convert
serverFn() output via JSON.stringify) to avoid Array<any> and any return types.

Source: Coding guidelines

e2e/react-start/session-handling/src/routes/ssr.tsx (1)

6-14: ⚡ Quick win

Replace Record<string, any> with Record<string, unknown> for strict type safety.

Line 7 uses Record<string, any> which violates the TypeScript strict mode guideline.

♻️ Suggested fix
 const loadSession = createServerFn().handler(async () => {
-  const session = await useSession<Record<string, any>>(sessionConfig())
+  const session = await useSession<Record<string, unknown>>(sessionConfig())
   const count = Number(session.data.ssrCount ?? 0) + 1
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/react-start/session-handling/src/routes/ssr.tsx` around lines 6 - 14, The
handler type for loadSession uses Record<string, any>; update it to use
Record<string, unknown> to satisfy strict TypeScript rules: locate the
createServerFn().handler callback where useSession<Record<string,
any>>(sessionConfig()) is called and change the generic to
useSession<Record<string, unknown>>(sessionConfig()), keeping the rest of the
logic (session.id, session.data, session.update) intact.

Source: Coding guidelines

e2e/react-start/session-handling/src/start.ts (1)

5-26: ⚡ Quick win

Replace Record<string, any> with Record<string, unknown> for strict type safety.

Lines 10 and 18 use Record<string, any> which violates the TypeScript strict mode guideline.

♻️ Suggested fix
     if (scenario === 'before') {
-      await updateSession<Record<string, any>>(sessionConfig(), {
+      await updateSession<Record<string, unknown>>(sessionConfig(), {
         middleware: 'before',
       })
       return next()
     }
 
     if (scenario === 'after') {
       const result = await next()
-      await updateSession<Record<string, any>>(sessionConfig(), {
+      await updateSession<Record<string, unknown>>(sessionConfig(), {
         middleware: 'after',
       })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/react-start/session-handling/src/start.ts` around lines 5 - 26, The two
updateSession calls inside the sessionMiddleware createMiddleware().server async
handler (the branches for scenario === 'before' and scenario === 'after') use
Record<string, any>; replace both type arguments with Record<string, unknown> to
comply with strict TypeScript typing (i.e., updateSession<Record<string,
unknown>>(sessionConfig(), { middleware: 'before' }) and similarly for the
'after' branch).

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@e2e/react-start/response-reconciliation/.gitignore`:
- Around line 14-15: The .gitignore entry "/public/build# Sentry Config File" is
malformed so "/public/build" won't be ignored; split the line into a pure
pattern and a comment: replace the single malformed line with a standalone
pattern "/public/build" and a separate comment line "# Sentry Config File"
(i.e., update the entry in response-reconciliation/.gitignore that currently
reads "/public/build# Sentry Config File").

In `@e2e/react-start/response-reconciliation/package.json`:
- Line 28: Update the internal dependency declaration for
"`@tanstack/router-e2e-utils`" in package.json to use the workspace protocol
exactly as "workspace:*" instead of "workspace:^"; locate the dependency entry
for "`@tanstack/router-e2e-utils`" and replace its version specifier "workspace:^"
with "workspace:*", then reinstall/update the lockfile to ensure consistent
dependency resolution.

In `@e2e/react-start/response-reconciliation/src/routes/server-functions.tsx`:
- Around line 46-55: The replacementMiddleware is using an `as any` escape to
return a Response—remove the `as any` and either cast through unknown to the
declared server middleware result type or update
FunctionMiddlewareServerFnResult to include Response so the returned new
Response is representable; specifically modify the return cast in the anonymous
function created by createMiddleware({ type: 'function' }).server(...) (the
block that checks resultWithResponse.result instanceof Response and returns new
Response) to use an `unknown`-based cast or extend
FunctionMiddlewareServerFnResult to accept Response. Also change
ServerFunctionButton’s `fn` prop type from Array<any>/Promise<any> to a safer
signature like `(...args: Array<unknown>) => Promise<unknown>` so callers retain
the instanceof Response check without `any`.

In `@e2e/react-start/session-handling/package.json`:
- Line 28: The dependency entry for `@tanstack/router-e2e-utils` uses the wrong
workspace protocol ("workspace:^"); update the package.json dependency for
"`@tanstack/router-e2e-utils`" to use the workspace protocol exactly as
"workspace:*" so it follows the repo's internal dependency rule; locate the
dependency in e2e/react-start/session-handling/package.json and replace the
version specifier accordingly.

In `@e2e/react-start/session-handling/src/routes/api/session-seal.ts`:
- Line 10: The session is currently typed as Record<string, any> which disables
strict typing; define a concrete session type (e.g., interface SessionData { /*
fields used below */ }) or use unknown with runtime type checks, then replace
useSession<Record<string, any>>(config) with useSession<SessionData>(config) (or
useSession<unknown>(config) plus narrow at runtime) and update any code that
accesses session properties to conform to the new type (adjust property names on
the SessionData interface to match existing usage).

---

Nitpick comments:
In `@e2e/react-start/session-handling/src/routes/server-functions.tsx`:
- Around line 16-22: In readSessionFn replace the loose generic Record<string,
any> passed to useSession with Record<string, unknown> to satisfy strict
TypeScript rules; update any downstream usages in the handler that assume
mutable or specific typed values from session.data to use type-safe access or
narrow/cast as needed (refer to readSessionFn, useSession, and sessionConfig to
locate the call).
- Around line 7-14: Change the session generic from Record<string, any> to
Record<string, unknown> in the updateSessionFn handler: locate the
createServerFn().handler block where useSession<Record<string,
any>>(sessionConfig()) is called and update the generic to use Record<string,
unknown> (affecting updateSessionFn and its use of useSession/sessionConfig) to
enforce strict TypeScript safety without losing flexibility.
- Around line 41-70: The parameter types using any are too loose; change the fn
prop type from (...args: Array<any>) => Promise<any> to (...args: unknown[]) =>
Promise<unknown> (or an appropriate specific generic) and update the useServerFn
invocation to pass/declare that same generic so TypeScript infers safer types
for serverFn (e.g., useServerFn<typeof fn> or useServerFn<(...args: unknown[])
=> Promise<unknown>>(fn)); also update any local uses/annotations that relied on
any (for example ensure result state remains a string but document/convert
serverFn() output via JSON.stringify) to avoid Array<any> and any return types.

In `@e2e/react-start/session-handling/src/routes/ssr.tsx`:
- Around line 6-14: The handler type for loadSession uses Record<string, any>;
update it to use Record<string, unknown> to satisfy strict TypeScript rules:
locate the createServerFn().handler callback where useSession<Record<string,
any>>(sessionConfig()) is called and change the generic to
useSession<Record<string, unknown>>(sessionConfig()), keeping the rest of the
logic (session.id, session.data, session.update) intact.

In `@e2e/react-start/session-handling/src/session.ts`:
- Around line 23-31: In readSession, replace the loose generic Record<string,
any> passed to useSession with Record<string, unknown> to conform to strict
TypeScript; update the useSession<Record<string, unknown>>(...) type argument
and ensure any downstream accesses to session.data or session.id are
typed/guarded appropriately (function names: readSession and useSession,
identifier: session.data/session.id).
- Around line 15-21: The readJson function currently swallows all JSON parse
errors and returns {} silently; modify readJson to catch the error as a variable
(e.g., catch (err)) and either log the error details (using console.error or the
project logger) before returning {} or rethrow the error so callers can handle
it; optionally add a boolean parameter like suppressErrors (default true) to
preserve current behavior in tests while allowing callers to surface errors when
needed.
- Around line 33-45: The function updateSessionData uses useSession with an
explicit type Record<string, any> which breaks strict TypeScript rules; change
that generic to Record<string, unknown> so the call becomes
useSession<Record<string, unknown>>(sessionConfig(overrides)), ensure any local
references to session.data or returned types are compatible with unknown (e.g.,
keep them typed as unknown instead of any) and run type checks to fix any
resulting type errors in updateSessionData, useSession, or sessionConfig.

In `@e2e/react-start/session-handling/src/start.ts`:
- Around line 5-26: The two updateSession calls inside the sessionMiddleware
createMiddleware().server async handler (the branches for scenario === 'before'
and scenario === 'after') use Record<string, any>; replace both type arguments
with Record<string, unknown> to comply with strict TypeScript typing (i.e.,
updateSession<Record<string, unknown>>(sessionConfig(), { middleware: 'before'
}) and similarly for the 'after' branch).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 23200d41-9026-4b02-bf02-6895e9cb3185

📥 Commits

Reviewing files that changed from the base of the PR and between 6f1daf5 and fe11405.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (86)
  • .changeset/start-response-state.md
  • docs/start/framework/react/guide/server-entry-point.md
  • e2e/react-start/response-reconciliation/.gitignore
  • e2e/react-start/response-reconciliation/.prettierignore
  • e2e/react-start/response-reconciliation/package.json
  • e2e/react-start/response-reconciliation/playwright.config.ts
  • e2e/react-start/response-reconciliation/rsbuild.config.ts
  • e2e/react-start/response-reconciliation/server.js
  • e2e/react-start/response-reconciliation/src/components/DefaultCatchBoundary.tsx
  • e2e/react-start/response-reconciliation/src/components/NotFound.tsx
  • e2e/react-start/response-reconciliation/src/routeTree.gen.ts
  • e2e/react-start/response-reconciliation/src/router.tsx
  • e2e/react-start/response-reconciliation/src/routes/__root.tsx
  • e2e/react-start/response-reconciliation/src/routes/api/-response.ts
  • e2e/react-start/response-reconciliation/src/routes/api/base.ts
  • e2e/react-start/response-reconciliation/src/routes/api/bulk-headers.ts
  • e2e/react-start/response-reconciliation/src/routes/api/clear-returned-headers.ts
  • e2e/react-start/response-reconciliation/src/routes/api/direct-mutation-visible.ts
  • e2e/react-start/response-reconciliation/src/routes/api/explicit-set-cookie-header.ts
  • e2e/react-start/response-reconciliation/src/routes/api/get-response-header-helper.ts
  • e2e/react-start/response-reconciliation/src/routes/api/get-response-headers-helper.ts
  • e2e/react-start/response-reconciliation/src/routes/api/multiple-cookies.ts
  • e2e/react-start/response-reconciliation/src/routes/api/null-body-status.ts
  • e2e/react-start/response-reconciliation/src/routes/api/readonly-after-next.ts
  • e2e/react-start/response-reconciliation/src/routes/api/redirect-with-cookies.ts
  • e2e/react-start/response-reconciliation/src/routes/api/remove-returned-header.ts
  • e2e/react-start/response-reconciliation/src/routes/api/replace-after-direct-mutation.ts
  • e2e/react-start/response-reconciliation/src/routes/api/replace-explicit-set-cookie.ts
  • e2e/react-start/response-reconciliation/src/routes/api/route-after-next.ts
  • e2e/react-start/response-reconciliation/src/routes/api/route-before-next.ts
  • e2e/react-start/response-reconciliation/src/routes/api/same-boundary-conflict.ts
  • e2e/react-start/response-reconciliation/src/routes/api/throw-after-status.ts
  • e2e/react-start/response-reconciliation/src/routes/api/two-returned-responses.ts
  • e2e/react-start/response-reconciliation/src/routes/index.tsx
  • e2e/react-start/response-reconciliation/src/routes/server-functions.tsx
  • e2e/react-start/response-reconciliation/src/routes/ssr.tsx
  • e2e/react-start/response-reconciliation/src/server-entry.ts
  • e2e/react-start/response-reconciliation/src/start.ts
  • e2e/react-start/response-reconciliation/src/styles/app.css
  • e2e/react-start/response-reconciliation/tests/response-reconciliation.spec.ts
  • e2e/react-start/response-reconciliation/tsconfig.json
  • e2e/react-start/response-reconciliation/vite.config.ts
  • e2e/react-start/session-handling/.gitignore
  • e2e/react-start/session-handling/.prettierignore
  • e2e/react-start/session-handling/package.json
  • e2e/react-start/session-handling/playwright.config.ts
  • e2e/react-start/session-handling/rsbuild.config.ts
  • e2e/react-start/session-handling/server.js
  • e2e/react-start/session-handling/src/components/DefaultCatchBoundary.tsx
  • e2e/react-start/session-handling/src/components/NotFound.tsx
  • e2e/react-start/session-handling/src/routeTree.gen.ts
  • e2e/react-start/session-handling/src/router.tsx
  • e2e/react-start/session-handling/src/routes/__root.tsx
  • e2e/react-start/session-handling/src/routes/api/session-clear.ts
  • e2e/react-start/session-handling/src/routes/api/session-cookie-disabled.ts
  • e2e/react-start/session-handling/src/routes/api/session-header.ts
  • e2e/react-start/session-handling/src/routes/api/session-helper-cookie.ts
  • e2e/react-start/session-handling/src/routes/api/session-middleware.ts
  • e2e/react-start/session-handling/src/routes/api/session-named.ts
  • e2e/react-start/session-handling/src/routes/api/session-seal.ts
  • e2e/react-start/session-handling/src/routes/api/session.ts
  • e2e/react-start/session-handling/src/routes/index.tsx
  • e2e/react-start/session-handling/src/routes/server-functions.tsx
  • e2e/react-start/session-handling/src/routes/ssr.tsx
  • e2e/react-start/session-handling/src/session.ts
  • e2e/react-start/session-handling/src/start.ts
  • e2e/react-start/session-handling/src/styles/app.css
  • e2e/react-start/session-handling/tests/session-handling.spec.ts
  • e2e/react-start/session-handling/tsconfig.json
  • e2e/react-start/session-handling/vite.config.ts
  • packages/react-start/src/default-entry/server.ts
  • packages/solid-start/src/default-entry/server.ts
  • packages/start-plugin-core/src/vite/plugin.ts
  • packages/start-plugin-core/tests/entry-planning.test.ts
  • packages/start-server-core/docs/RECONCILIATION.md
  • packages/start-server-core/package.json
  • packages/start-server-core/skills/start-server-core/SKILL.md
  • packages/start-server-core/src/createStartHandler.ts
  • packages/start-server-core/src/headers.ts
  • packages/start-server-core/src/internal-request-response.ts
  • packages/start-server-core/src/request-response.ts
  • packages/start-server-core/src/server-functions-handler.ts
  • packages/start-server-core/tests/createStartHandler.test.ts
  • packages/start-server-core/tests/server-functions-handler.test.ts
  • packages/start-server-core/vite.config.ts
  • packages/vue-start/src/default-entry/server.ts

Comment on lines +14 to +15
/public/build# Sentry Config File
.env.sentry-build-plugin

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix malformed ignore entry on Line 14.

/public/build# Sentry Config File is parsed as one literal pattern, so /public/build may not be ignored as intended.

Suggested patch
-/public/build# Sentry Config File
+# Sentry Config File
+/public/build
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/public/build# Sentry Config File
.env.sentry-build-plugin
# Sentry Config File
/public/build
.env.sentry-build-plugin
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/react-start/response-reconciliation/.gitignore` around lines 14 - 15, The
.gitignore entry "/public/build# Sentry Config File" is malformed so
"/public/build" won't be ignored; split the line into a pure pattern and a
comment: replace the single malformed line with a standalone pattern
"/public/build" and a separate comment line "# Sentry Config File" (i.e., update
the entry in response-reconciliation/.gitignore that currently reads
"/public/build# Sentry Config File").

"@playwright/test": "^1.57.0",
"@rsbuild/core": "^2.0.8",
"@rsbuild/plugin-react": "^2.0.0",
"@tanstack/router-e2e-utils": "workspace:^",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use workspace:* for internal dependency on Line 28.

@tanstack/router-e2e-utils is currently workspace:^; this conflicts with the repository rule for internal packages.

As per coding guidelines, "**/package.json: Use workspace protocol (workspace:*) for internal dependencies".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/react-start/response-reconciliation/package.json` at line 28, Update the
internal dependency declaration for "`@tanstack/router-e2e-utils`" in package.json
to use the workspace protocol exactly as "workspace:*" instead of "workspace:^";
locate the dependency entry for "`@tanstack/router-e2e-utils`" and replace its
version specifier "workspace:^" with "workspace:*", then reinstall/update the
lockfile to ensure consistent dependency resolution.

Source: Coding guidelines

Comment on lines +46 to +55
const resultWithResponse = result as typeof result & { result?: unknown }
if (!(resultWithResponse.result instanceof Response)) {
throw new Error('Expected replacement test to observe a Response')
}
resultWithResponse.result.headers.set('x-function-a', 'yes')
setResponseHeader('x-function-helper-delta', 'yes')
return new Response('function-b', {
headers: { 'x-function-b': 'yes' },
}) as any
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="e2e/react-start/response-reconciliation/src/routes/server-functions.tsx"

echo "== File check =="
ls -la "$FILE"

echo "== Occurrences of 'as any' and 'any' in file =="
rg -n "as any|:\s*any|\bany\b|Array<any>|Promise<any>" "$FILE" || true

echo "== Show around the referenced lines (40-80) =="
nl -ba "$FILE" | sed -n '35,90p'

echo "== Show around the referenced lines (160-220) =="
nl -ba "$FILE" | sed -n '150,230p'

Repository: TanStack/router

Length of output: 417


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="e2e/react-start/response-reconciliation/src/routes/server-functions.tsx"

echo "== Show around lines 46-55 (38-65) =="
awk 'NR>=38 && NR<=65 {printf "%d:%s\n", NR, $0}' "$FILE"

echo "== Show around lines 177-183 (170-190) =="
awk 'NR>=170 && NR<=190 {printf "%d:%s\n", NR, $0}' "$FILE"

Repository: TanStack/router

Length of output: 1592


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="e2e/react-start/response-reconciliation/src/routes/server-functions.tsx"

echo "== File header/imports =="
awk 'NR>=1 && NR<=80 {printf "%d:%s\n", NR, $0}' "$FILE"

echo "== Types/usage around ServerFunctionButton =="
awk 'NR>=120 && NR<=210 {printf "%d:%s\n", NR, $0}' "$FILE"

echo "== Find createMiddleware usage signature context =="
rg -n "createMiddleware\\(" "$FILE"
echo "== Find createServerFn / useServerFn definitions in this repo =="
rg -n "useServerFn\\(" -S e2e/react-start/response-reconciliation/src/routes/server-functions.tsx
rg -n "function useServerFn|const useServerFn|useServerFn<" -S . || true

Repository: TanStack/router

Length of output: 6503


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Inspect useServerFn signature =="
sed -n '1,120p' packages/react-start/src/useServerFn.ts

echo "== Find createMiddleware typing/implementation =="
rg -n "export function createMiddleware|function createMiddleware|createMiddleware\\s*\\(" packages -S

echo "== Show createMiddleware definition around match(s) =="
# Print only the first couple matches with context
MATCHES=$(rg -n "createMiddleware\\s*\\(" packages -S | head -n 5 | cut -d: -f1-2)
echo "$MATCHES" | head -n 5

# For each matched file, print top section (best-effort)
# Note: if too many, we still limit output
files=$(rg -l "createMiddleware\\s*\\(" packages -S | head -n 5)
for f in $files; do
  echo "---- $f (top) ----"
  sed -n '1,140p' "$f"
done

echo "== Find createMiddleware server() return type constraints =="
rg -n "\\.server\\(" packages -S | head -n 20

Repository: TanStack/router

Length of output: 41791


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE="e2e/react-start/response-reconciliation/src/routes/server-functions.tsx"

echo "== createServerFn definitions (lines 55-180) =="
awk 'NR>=55 && NR<=180 {printf "%d:%s\n", NR, $0}' "$FILE"

echo "== Functions passed into <ServerFunctionButton ... fn={...} /> =="
rg -n "<ServerFunctionButton[^>]*\\sfn=\\{[^}]+\\}" "$FILE"

Repository: TanStack/router

Length of output: 4626


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate createMiddleware source/typings used by `@tanstack/react-start`
rg -n "export (function|const) createMiddleware|function createMiddleware|createMiddleware\\s*\\(" packages/react-start packages/start-client-core packages/start-client-* packages/start-* -S --glob='*.ts' --glob='*.tsx' --glob='*.d.ts' || true

# Show the actual createMiddleware implementation/types (best-effort, pick likely files)
for f in $(rg -l "createMiddleware" packages/react-start/src packages/start-client-core/src packages/start-client-core/src -S --glob='*.ts' --glob='*.d.ts' | head -n 20); do
  echo "---- $f (head) ----"
  sed -n '1,200p' "$f" | head -n 200
done

# Also inspect where createMiddleware is re-exported from `@tanstack/react-start`
rg -n "createMiddleware" packages/react-start/src -S --glob='*.ts' --glob='*.tsx' --glob='*.d.ts' || true

Repository: TanStack/router

Length of output: 50372


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE="packages/start-client-core/src/createMiddleware.ts"

echo "== createMiddleware.ts (first 260 lines) =="
sed -n '1,260p' "$FILE"

echo "== createMiddleware.ts (next 260 lines) =="
sed -n '261,520p' "$FILE"

echo "== createMiddleware.ts (tail 120 lines) =="
tail -n 120 "$FILE"

Repository: TanStack/router

Length of output: 17311


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE="packages/start-client-core/src/createMiddleware.ts"

rg -n "FunctionMiddlewareServerFnResult" "$FILE"
echo "== Around matches (context) =="
# Print a window around the first few matches
rg -n "FunctionMiddlewareServerFnResult" "$FILE" | cut -d: -f1 | head -n 5 | while read -r ln; do
  start=$((ln-40))
  end=$((ln+120))
  echo "---- lines ${start}-${end} (centered at $ln) ----"
  sed -n "${start},${end}p" "$FILE"
done

Repository: TanStack/router

Length of output: 7472


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Search for function-middleware server() returning Response
rg -n "createMiddleware\\(\\{\\s*type:\\s*'function'\\s*\\}\\)\\.[a-zA-Z]+\\([^\\)]*\\)\\s*=>\\s*new Response|createMiddleware\\(\\{\\s*type:\\s*'function'\\s*\\}\\)\\.server\\([\\s\\S]*?new Response" -S .
# More direct: just look for "new Response" inside server() callbacks for function middleware
rg -n "createMiddleware\\(\\{[^}]*type:\\s*'function'[^}]*\\}\\)\\s*\\.[a-zA-Z]+\\([^\\)]*\\)|createMiddleware\\(\\{[^}]*type:\\s*'function'[^}]*\\}\\)\\s*\\.server\\(" -S e2e/react-start/response-reconciliation/src/routes/server-functions.tsx
rg -n "new Response\\(" -S e2e/react-start/response-reconciliation/src/routes/server-functions.tsx

# Broad search for createMiddleware({ type: 'function' }).server with "new Response"
rg -n "createMiddleware\\(\\{[^}]*type:\\s*'function'[^}]*\\}\\)\\.server\\([\\s\\S]{0,300}?new Response\\(" -S packages e2e start . || true

# Broad search for "as any" near Response in createMiddleware callbacks
rg -n "createMiddleware\\(\\{[^}]*type:\\s*'function'[^}]*\\}\\)\\.server[\\s\\S]{0,200}?as any|new Response\\([\\s\\S]{0,200}?as any" -S packages e2e start . || true

Repository: TanStack/router

Length of output: 41


Replace explicit any escapes in server-functions.tsx to preserve strict TS guarantees

  • replacementMiddleware currently returns a new Response(...) from createMiddleware({ type: 'function' }).server(...) and uses as any at line 54; FunctionMiddlewareServerFnResult does not include Response in packages/start-client-core/src/createMiddleware.ts, so this is papering over a type mismatch—replace as any with an unknown-based cast or adjust the middleware/result typing so the Response replacement is represented without any.
  • ServerFunctionButton’s fn prop uses Array<any>/Promise<any> at line 182; change to (...args: Array<unknown>) => Promise<unknown> to avoid any while keeping the existing instanceof Response handling.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/react-start/response-reconciliation/src/routes/server-functions.tsx`
around lines 46 - 55, The replacementMiddleware is using an `as any` escape to
return a Response—remove the `as any` and either cast through unknown to the
declared server middleware result type or update
FunctionMiddlewareServerFnResult to include Response so the returned new
Response is representable; specifically modify the return cast in the anonymous
function created by createMiddleware({ type: 'function' }).server(...) (the
block that checks resultWithResponse.result instanceof Response and returns new
Response) to use an `unknown`-based cast or extend
FunctionMiddlewareServerFnResult to accept Response. Also change
ServerFunctionButton’s `fn` prop type from Array<any>/Promise<any> to a safer
signature like `(...args: Array<unknown>) => Promise<unknown>` so callers retain
the instanceof Response check without `any`.

Source: Coding guidelines

"@playwright/test": "^1.57.0",
"@rsbuild/core": "^2.0.8",
"@rsbuild/plugin-react": "^2.0.0",
"@tanstack/router-e2e-utils": "workspace:^",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use workspace:* for internal dependency versions.

Line 28 uses workspace:^ for @tanstack/router-e2e-utils, which violates the workspace versioning rule used in this repo.

As per coding guidelines, **/package.json must "Use workspace protocol (workspace:*) for internal dependencies".

Proposed fix
-    "`@tanstack/router-e2e-utils`": "workspace:^",
+    "`@tanstack/router-e2e-utils`": "workspace:*",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"@tanstack/router-e2e-utils": "workspace:^",
"`@tanstack/router-e2e-utils`": "workspace:*",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/react-start/session-handling/package.json` at line 28, The dependency
entry for `@tanstack/router-e2e-utils` uses the wrong workspace protocol
("workspace:^"); update the package.json dependency for
"`@tanstack/router-e2e-utils`" to use the workspace protocol exactly as
"workspace:*" so it follows the repo's internal dependency rule; locate the
dependency in e2e/react-start/session-handling/package.json and replace the
version specifier accordingly.

Source: Coding guidelines

handlers: {
POST: async ({ request }) => {
const config = sessionConfig({ cookie: false })
const session = await useSession<Record<string, any>>(config)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove any from session data typing.

Line 10 uses Record<string, any>, which bypasses strict typing in a TS-strict workspace.

As per coding guidelines, **/*.{ts,tsx} should "Use TypeScript strict mode with extensive type safety".

Proposed fix
-        const session = await useSession<Record<string, any>>(config)
+        const session = await useSession<Record<string, unknown>>(config)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const session = await useSession<Record<string, any>>(config)
const session = await useSession<Record<string, unknown>>(config)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@e2e/react-start/session-handling/src/routes/api/session-seal.ts` at line 10,
The session is currently typed as Record<string, any> which disables strict
typing; define a concrete session type (e.g., interface SessionData { /* fields
used below */ }) or use unknown with runtime type checks, then replace
useSession<Record<string, any>>(config) with useSession<SessionData>(config) (or
useSession<unknown>(config) plus narrow at runtime) and update any code that
accesses session properties to conform to the new type (adjust property names on
the SessionData interface to match existing usage).

Source: Coding guidelines

@schiller-manuel schiller-manuel force-pushed the response-reconciliation branch from fe11405 to 97e14ca Compare June 8, 2026 22:10
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

🚀 Changeset Version Preview

8 package(s) bumped directly, 8 bumped as dependents.

🟩 Patch bumps

Package Version Reason
@tanstack/react-router 1.170.15 → 1.170.16 Changeset
@tanstack/react-start 1.168.25 → 1.168.26 Changeset
@tanstack/solid-router 1.170.15 → 1.170.16 Changeset
@tanstack/solid-start 1.168.25 → 1.168.26 Changeset
@tanstack/start-client-core 1.170.12 → 1.170.13 Changeset
@tanstack/start-plugin-core 1.171.17 → 1.171.18 Changeset
@tanstack/start-server-core 1.169.14 → 1.169.15 Changeset
@tanstack/vue-start 1.168.24 → 1.168.25 Changeset
@tanstack/react-start-client 1.168.13 → 1.168.14 Dependent
@tanstack/react-start-rsc 0.1.24 → 0.1.25 Dependent
@tanstack/react-start-server 1.167.19 → 1.167.20 Dependent
@tanstack/solid-start-client 1.168.13 → 1.168.14 Dependent
@tanstack/solid-start-server 1.167.19 → 1.167.20 Dependent
@tanstack/start-static-server-functions 1.167.17 → 1.167.18 Dependent
@tanstack/vue-start-client 1.167.17 → 1.167.18 Dependent
@tanstack/vue-start-server 1.167.19 → 1.167.20 Dependent

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Bundle Size Benchmarks

  • Commit: dbe8fd89fb8d
  • Measured at: 2026-06-08T22:12:21.069Z
  • Baseline source: history:41e7a24f693b
  • Dashboard: bundle-size history
Scenario Current (gzip) Delta vs baseline Initial gzip Raw Brotli Trend
react-router.minimal 87.25 KiB 0 B (0.00%) 87.11 KiB 273.59 KiB 75.96 KiB ██▂▂▂▂▂▂▁▃▃
react-router.full 90.98 KiB 0 B (0.00%) 90.84 KiB 285.48 KiB 79.13 KiB ██▇▇▇▇▇▇▁▁▁
solid-router.minimal 35.48 KiB 0 B (0.00%) 35.36 KiB 105.86 KiB 32.03 KiB ▃▃▆▆▆▆▆▆▆█▁
solid-router.full 40.53 KiB 0 B (0.00%) 40.41 KiB 121.08 KiB 36.46 KiB ██▄▄▄▄▄▄▄▅▁
vue-router.minimal 52.97 KiB 0 B (0.00%) 52.84 KiB 149.90 KiB 47.62 KiB ██▆▆▆▆▆▆▆▁▁
vue-router.full 58.96 KiB 0 B (0.00%) 58.83 KiB 168.66 KiB 52.87 KiB ██▁▁▁▁▁▁▁▅▅
react-start.minimal 101.88 KiB 0 B (0.00%) 101.75 KiB 321.90 KiB 88.14 KiB ▅▅▁▁▁▁▁▁▁██
react-start.deferred-hydration 102.62 KiB 0 B (0.00%) 101.77 KiB 323.28 KiB 88.85 KiB ▇▇▁▁▁▁▁▁▇██
react-start.full 105.27 KiB 0 B (0.00%) 105.13 KiB 331.84 KiB 91.03 KiB ▃▃▃▃████▁▁▁
react-start.rsbuild.minimal 99.59 KiB 0 B (0.00%) 99.42 KiB 316.35 KiB 85.75 KiB ▅▅██████▁▅▅
react-start.rsbuild.minimal-iife 99.99 KiB 0 B (0.00%) 99.83 KiB 317.29 KiB 86.07 KiB ▄▄██████▁▆▆
react-start.rsbuild.full 102.81 KiB 0 B (0.00%) 102.64 KiB 326.41 KiB 88.40 KiB ▄▄▅▅████▁▁▁
solid-start.minimal 49.60 KiB 0 B (0.00%) 49.47 KiB 151.93 KiB 43.79 KiB ▁▁▇▇▇▇▇▇▇█▂
solid-start.deferred-hydration 52.86 KiB 0 B (0.00%) 49.53 KiB 159.97 KiB 46.81 KiB ▁▁▆▆▆▆▆▆▆█▅
solid-start.full 55.40 KiB 0 B (0.00%) 55.27 KiB 168.97 KiB 48.80 KiB ▃▃▁▁▇▇▇▇▇█▆
vue-start.minimal 71.02 KiB 0 B (0.00%) 70.89 KiB 207.04 KiB 62.93 KiB ▂▂▁▁▁▁▁▁▁██
vue-start.full 75.01 KiB 0 B (0.00%) 74.88 KiB 219.68 KiB 66.40 KiB ▂▂▁▁▇▇▇▇▇██

Current gzip tracks all emitted client JS chunks. Initial gzip tracks only the entry/import graph. Trend sparkline is historical current gzip ending with this PR measurement; lower is better.

@pkg-pr-new

pkg-pr-new Bot commented Jun 8, 2026

Copy link
Copy Markdown
More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/@tanstack/arktype-adapter@7588

@tanstack/eslint-plugin-router

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

@tanstack/eslint-plugin-start

npm i https://pkg.pr.new/@tanstack/eslint-plugin-start@7588

@tanstack/history

npm i https://pkg.pr.new/@tanstack/history@7588

@tanstack/nitro-v2-vite-plugin

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

@tanstack/react-router

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

@tanstack/react-router-devtools

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

@tanstack/react-router-ssr-query

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

@tanstack/react-start

npm i https://pkg.pr.new/@tanstack/react-start@7588

@tanstack/react-start-client

npm i https://pkg.pr.new/@tanstack/react-start-client@7588

@tanstack/react-start-rsc

npm i https://pkg.pr.new/@tanstack/react-start-rsc@7588

@tanstack/react-start-server

npm i https://pkg.pr.new/@tanstack/react-start-server@7588

@tanstack/router-cli

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

@tanstack/router-core

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

@tanstack/router-devtools

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

@tanstack/router-devtools-core

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

@tanstack/router-generator

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

@tanstack/router-plugin

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

@tanstack/router-ssr-query-core

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

@tanstack/router-utils

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

@tanstack/router-vite-plugin

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

@tanstack/solid-router

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

@tanstack/solid-router-devtools

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

@tanstack/solid-router-ssr-query

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

@tanstack/solid-start

npm i https://pkg.pr.new/@tanstack/solid-start@7588

@tanstack/solid-start-client

npm i https://pkg.pr.new/@tanstack/solid-start-client@7588

@tanstack/solid-start-server

npm i https://pkg.pr.new/@tanstack/solid-start-server@7588

@tanstack/start-client-core

npm i https://pkg.pr.new/@tanstack/start-client-core@7588

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/@tanstack/start-fn-stubs@7588

@tanstack/start-plugin-core

npm i https://pkg.pr.new/@tanstack/start-plugin-core@7588

@tanstack/start-server-core

npm i https://pkg.pr.new/@tanstack/start-server-core@7588

@tanstack/start-static-server-functions

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

@tanstack/start-storage-context

npm i https://pkg.pr.new/@tanstack/start-storage-context@7588

@tanstack/valibot-adapter

npm i https://pkg.pr.new/@tanstack/valibot-adapter@7588

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/@tanstack/virtual-file-routes@7588

@tanstack/vue-router

npm i https://pkg.pr.new/@tanstack/vue-router@7588

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/@tanstack/vue-router-devtools@7588

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/@tanstack/vue-router-ssr-query@7588

@tanstack/vue-start

npm i https://pkg.pr.new/@tanstack/vue-start@7588

@tanstack/vue-start-client

npm i https://pkg.pr.new/@tanstack/vue-start-client@7588

@tanstack/vue-start-server

npm i https://pkg.pr.new/@tanstack/vue-start-server@7588

@tanstack/zod-adapter

npm i https://pkg.pr.new/@tanstack/zod-adapter@7588

commit: 97e14ca

@nx-cloud nx-cloud Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nx Cloud is proposing a fix for your failed CI:

We updated requestHandler in internal-request-response.ts to validate the URL pathname with decodeURIComponent after URL parsing, which restores the 400 Bad Request behaviour for malformed UTF-8 percent-encoded sequences (e.g. %E0%A4, %80, %FF) that was previously provided by H3Event's constructor. Without this fix, the WHATWG URL parser silently accepts those byte sequences and the request falls through to the router, resulting in a 404 instead of the expected 400.

Tip

We verified this fix by re-running @tanstack/vue-router:test:unit, tanstack-react-start-e2e-basic:test:e2e--vite-prerender.

diff --git a/packages/start-server-core/src/internal-request-response.ts b/packages/start-server-core/src/internal-request-response.ts
index ae8f1a6d..fc615534 100644
--- a/packages/start-server-core/src/internal-request-response.ts
+++ b/packages/start-server-core/src/internal-request-response.ts
@@ -674,6 +674,18 @@ export function requestHandler<TRegister = unknown>(
       throw error
     }
 
+    try {
+      decodeURIComponent(requestUrl.pathname)
+    } catch (error) {
+      if (error instanceof URIError) {
+        return new Response(null, {
+          status: 400,
+          statusText: 'Bad Request',
+        })
+      }
+      throw error
+    }
+
     const response = createStartResponse()
     const responseMeta = createResponseMeta()
     trackStartResponse(response, responseMeta)

Apply fix via Nx Cloud  Reject fix via Nx Cloud


Or Apply changes locally with:

npx nx-cloud apply-locally bI6l-OhXi

Apply fix locally with your editor ↗   View interactive diff ↗



🎓 Learn more about Self-Healing CI on nx.dev

@codspeed-hq

codspeed-hq Bot commented Jun 8, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 6 untouched benchmarks


Comparing response-reconciliation (97e14ca) with main (41e7a24)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (6f1daf5) during the generation of this report, so 41e7a24 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

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

Projects

None yet

1 participant