Skip to content

Conversation

schiller-manuel
Copy link
Contributor

@schiller-manuel schiller-manuel commented Sep 28, 2025

fixes #5271

fixes #5255

Summary by CodeRabbit

  • New Features

    • Server functions can return Response objects (sync or async); clients may receive raw Response objects that bypass normal content-type handling when marked.
    • Added a public constant to indicate raw responses.
  • Tests

    • Updated type-level tests to cover async/sync handlers returning Response, arrays, and union types ensuring server function return types are Promise-wrapped as expected.

Copy link
Contributor

coderabbitai bot commented Sep 28, 2025

Walkthrough

Adds a raw-response pathway: new X_TSS_RAW_RESPONSE constant (exported), server sets this header when returning a Response, client fetcher short-circuits and returns the raw Response, and server function return types/tests updated to allow Promise<Response>.

Changes

Cohort / File(s) Summary of Changes
Client constants & exports
packages/start-client-core/src/constants.ts, packages/start-client-core/src/index.tsx
Added and re-exported X_TSS_RAW_RESPONSE = 'x-tss-raw'.
Client fetcher control flow
packages/start-client-core/src/client-rpc/serverFnFetcher.ts
Imported X_TSS_RAW_RESPONSE and added early-return: if response header x-tss-raw === 'true', return the raw Response immediately, bypassing content-type handling and serialization.
Server function typing & tests
packages/start-client-core/src/createServerFn.ts, packages/start-client-core/src/tests/createServerFn.test-d.ts
Extended ServerFnReturnType to include Promise<Response> and updated type-coverage tests to cover async/sync handlers returning Response, arrays, and unions.
Server handler integration
packages/start-server-core/src/server-functions-handler.ts
Imported X_TSS_RAW_RESPONSE and sets header x-tss-raw: "true" when returning a Response from a handler to signal raw response to clients.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor U as User Code
  participant C as Client API
  participant F as serverFnFetcher
  participant S as Server handler

  U->>C: call serverFn(...)
  C->>F: invoke fetcher
  F->>S: HTTP request
  alt Server returns raw Response
    S-->>F: Response (headers include x-tss-raw: "true")
    note right of F #DDEBF7: fetcher detects header\nand short-circuits
    F-->>C: return raw Response
    C-->>U: Response
  else Server returns serialized payload
    S-->>F: serialized body (JSON)
    F->>F: parse & deserialize
    F-->>C: structured data
    C-->>U: data
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • chorobin

Poem

I thump my paw—response anew,
A tiny header lets raw shine through.
No more undefined surprise,
Async Responses now pass the skies.
Hop, ship, done—carrots for you! 🥕

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title Check ✅ Passed The title succinctly captures the primary focus of the changes, namely fixing how raw Response objects are handled by both client and server code, without including extraneous details or listing individual files.
Linked Issues Check ✅ Passed The pull request directly addresses both issues from #5271 by having the server set the X_TSS_RAW_RESPONSE header when returning a Response and updating the client fetcher to bypass JSON parsing for raw responses, as well as extending the ServerFnReturnType union to include Promise and adding type-level tests to ensure no type errors occur when returning raw Response objects.
Out of Scope Changes Check ✅ Passed All modifications—including new constants, client and server logic, type definition updates, and related tests—are strictly related to enabling raw response support and resolving the linked issues, with no unrelated or extraneous changes introduced.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-async-response-type

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

Copy link

nx-cloud bot commented Sep 28, 2025

🤖 Nx Cloud AI Fix Eligible

An automatically generated fix could have helped fix failing tasks for this run, but Self-healing CI is disabled for this workspace. Visit workspace settings to enable it and get automatic fixes in future runs.

To disable these notifications, a workspace admin can disable them in workspace settings.


View your CI Pipeline Execution ↗ for commit 0cf7bfe

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ❌ Failed 1m 5s View ↗
nx run-many --target=build --exclude=examples/*... ❌ Failed 5s View ↗

☁️ Nx Cloud last updated this comment at 2025-09-28 18:32:04 UTC

Copy link

pkg-pr-new bot commented Sep 28, 2025

More templates

@tanstack/arktype-adapter

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

@tanstack/directive-functions-plugin

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

@tanstack/eslint-plugin-router

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

@tanstack/history

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

@tanstack/nitro-v2-vite-plugin

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

@tanstack/react-router

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

@tanstack/react-router-devtools

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

@tanstack/react-router-ssr-query

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

@tanstack/react-start

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

@tanstack/react-start-client

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

@tanstack/react-start-server

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

@tanstack/router-cli

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

@tanstack/router-core

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

@tanstack/router-devtools

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

@tanstack/router-devtools-core

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

@tanstack/router-generator

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

@tanstack/router-plugin

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

@tanstack/router-ssr-query-core

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

@tanstack/router-utils

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

@tanstack/router-vite-plugin

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

@tanstack/server-functions-plugin

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

@tanstack/solid-router

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

@tanstack/solid-router-devtools

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

@tanstack/solid-start

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

@tanstack/solid-start-client

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

@tanstack/solid-start-server

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

@tanstack/start-client-core

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

@tanstack/start-plugin-core

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

@tanstack/start-server-core

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

@tanstack/start-static-server-functions

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

@tanstack/start-storage-context

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

@tanstack/valibot-adapter

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

@tanstack/virtual-file-routes

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

@tanstack/zod-adapter

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

commit: dff3ae7

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 86b1dd9 and 13b3ecf.

📒 Files selected for processing (6)
  • packages/start-client-core/src/client-rpc/serverFnFetcher.ts (2 hunks)
  • packages/start-client-core/src/constants.ts (1 hunks)
  • packages/start-client-core/src/createServerFn.ts (1 hunks)
  • packages/start-client-core/src/index.tsx (1 hunks)
  • packages/start-client-core/src/tests/createServerFn.test-d.ts (2 hunks)
  • packages/start-server-core/src/server-functions-handler.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript in strict mode with extensive type safety across the codebase

Files:

  • packages/start-client-core/src/createServerFn.ts
  • packages/start-client-core/src/constants.ts
  • packages/start-client-core/src/client-rpc/serverFnFetcher.ts
  • packages/start-client-core/src/tests/createServerFn.test-d.ts
  • packages/start-server-core/src/server-functions-handler.ts
  • packages/start-client-core/src/index.tsx
packages/{*-start,start-*}/**

📄 CodeRabbit inference engine (AGENTS.md)

Name and place Start framework packages under packages/-start/ or packages/start-/

Files:

  • packages/start-client-core/src/createServerFn.ts
  • packages/start-client-core/src/constants.ts
  • packages/start-client-core/src/client-rpc/serverFnFetcher.ts
  • packages/start-client-core/src/tests/createServerFn.test-d.ts
  • packages/start-server-core/src/server-functions-handler.ts
  • packages/start-client-core/src/index.tsx
🧬 Code graph analysis (4)
packages/start-client-core/src/constants.ts (1)
packages/start-client-core/src/index.tsx (1)
  • X_TSS_RAW_RESPONSE (88-88)
packages/start-client-core/src/client-rpc/serverFnFetcher.ts (2)
packages/start-client-core/src/constants.ts (1)
  • X_TSS_RAW_RESPONSE (8-8)
packages/start-client-core/src/index.tsx (1)
  • X_TSS_RAW_RESPONSE (88-88)
packages/start-client-core/src/tests/createServerFn.test-d.ts (1)
packages/start-client-core/src/createServerFn.ts (1)
  • createServerFn (51-170)
packages/start-server-core/src/server-functions-handler.ts (2)
packages/start-client-core/src/constants.ts (1)
  • X_TSS_RAW_RESPONSE (8-8)
packages/start-client-core/src/index.tsx (1)
  • X_TSS_RAW_RESPONSE (88-88)
⏰ 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: Test
  • GitHub Check: Preview

Comment on lines +149 to 150
result.result.headers.set(X_TSS_RAW_RESPONSE, 'true')
return result.result
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Setting a header on an immutable Response will throw at runtime

When developers return a Response obtained from fetch (very common for proxying upstream resources), response.headers is immutable. Calling set on it throws TypeError: Headers guard is immutable, so this path will crash before the response ever reaches the client—precisely the scenario this PR is meant to fix. Instead of mutating the existing headers, clone them (and the response metadata) into a new Response that includes X_TSS_RAW_RESPONSE.

Apply this diff to fix the issue:

-      if (result.result instanceof Response) {
-        result.result.headers.set(X_TSS_RAW_RESPONSE, 'true')
-        return result.result
-      }
+      if (result.result instanceof Response) {
+        const rawResponse = result.result
+        const headers = new Headers(rawResponse.headers)
+        headers.set(X_TSS_RAW_RESPONSE, 'true')
+        return new Response(rawResponse.body, {
+          status: rawResponse.status,
+          statusText: rawResponse.statusText,
+          headers,
+        })
+      }
📝 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
result.result.headers.set(X_TSS_RAW_RESPONSE, 'true')
return result.result
if (result.result instanceof Response) {
const rawResponse = result.result
const headers = new Headers(rawResponse.headers)
headers.set(X_TSS_RAW_RESPONSE, 'true')
return new Response(rawResponse.body, {
status: rawResponse.status,
statusText: rawResponse.statusText,
headers,
})
}
🤖 Prompt for AI Agents
In packages/start-server-core/src/server-functions-handler.ts around lines
149-150, the code attempts to call result.result.headers.set(...) on a Response
returned from fetch, but fetch Responses have immutable headers and calling set
throws at runtime; instead, create a new Response cloning the original body and
metadata and use a mutable copy of the headers: construct a new
Headers(result.result.headers), call set('X-TSS-RAW_RESPONSE','true') on that
copy, then return new Response(result.result.body, { status:
result.result.status, statusText: result.result.statusText, headers:
headersCopy, /* copy any other relevant properties like duplex if used */ });
this avoids mutating the original immutable Headers and preserves the original
response metadata and body.

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.

Server function returns undefined on raw response value Raw Response from server function not working on Bun runtime
1 participant