Skip to content

fix(start-server-core): fall back to GET handler for HEAD requests (RFC 9110 §9.3.2)#7325

Merged
schiller-manuel merged 6 commits into
TanStack:mainfrom
Zelys-DFKH:fix/head-request-fallback-to-get-handler
May 3, 2026
Merged

fix(start-server-core): fall back to GET handler for HEAD requests (RFC 9110 §9.3.2)#7325
schiller-manuel merged 6 commits into
TanStack:mainfrom
Zelys-DFKH:fix/head-request-fallback-to-get-handler

Conversation

@Zelys-DFKH
Copy link
Copy Markdown
Contributor

@Zelys-DFKH Zelys-DFKH commented May 2, 2026

Fixes #7270.

RFC 9110 §9.3.2 requires HEAD responses to match GET in headers and status, with no body. When a route has no explicit HEAD handler, the server falls back to GET and strips the body.

What changed

  • Handler priority: HEAD now tries HEAD → GET → ANY. Previously ANY beat GET, so a route with both a GET and an ANY handler would skip the GET for HEAD requests entirely — wrong per RFC 9110.
  • Body stripping now covers the ANY fallback too, not just GET. If HEAD falls back to ANY, the body is stripped.
  • Redirect before strip: the old code stripped the body before resolving redirects, converting a RedirectResponse to a plain Response before handleRedirectResponse could process it. The Location header was lost as a result. The fix resolves the redirect first, then strips.
  • statusText is now copied to the stripped response.

E2E coverage

Three new Playwright tests in e2e/react-start/server-routes:

  • HEAD to a GET-only route: body empty, content-type preserved
  • HEAD to an ANY-only route: body empty, X-HANDLER: ANY and X-METHOD: HEAD preserved
  • HEAD to a route with both GET and ANY: GET wins, body empty

Test plan

  • pnpm test in packages/start-server-core
  • E2E tests pass in e2e/react-start/server-routes

Summary by CodeRabbit

  • New Features

    • Added three API endpoints: /api/head-fallback, /api/get-and-any, and /api/head-redirect-fallback.
  • Bug Fixes

    • HEAD requests now prefer HEAD → GET → ANY (RFC 9110), return empty bodies for HEAD fallbacks, preserve status/headers, and correctly resolve redirects.
  • Tests

    • Added end-to-end tests validating HEAD behavior, handler selection, header preservation, and redirect flow.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 2, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR makes HEAD requests to exact-match server file routes fall back HEAD → GET → ANY, strips the response body when the handler is not a native HEAD handler while preserving status/headers (including redirects), and adds route examples, tests, generated route-tree entries, and a changeset.

Changes

HEAD Request Fallback Implementation

Layer / File(s) Summary
Core Handler Logic
packages/start-server-core/src/createStartHandler.ts
HEAD handler selection changed to handlers.HEAD ?? handlers.GET ?? handlers.ANY; tracks isHeadFallback, resolves redirects when used, and returns new Response(null, resolved) to preserve headers/status but strip the body.
Server Routes (examples)
e2e/react-start/server-routes/src/routes/api/head-fallback.ts, e2e/react-start/server-routes/src/routes/api/get-and-any.ts, e2e/react-start/server-routes/src/routes/api/head-redirect-fallback.ts
Adds /api/head-fallback (GET-only, returns XML body/content-type), /api/get-and-any (GET and ANY handlers emitting x-handler/x-method), and /api/head-redirect-fallback (GET → 307 redirect to /api/head-fallback).
Route Registration (generated)
e2e/react-start/server-routes/src/routeTree.gen.ts
Imports, instantiates, and registers the three new routes; extends exported route type mappings and adds entries to RootRouteChildren and rootRouteChildren.
E2E Tests
e2e/react-start/server-routes/tests/server-routes.spec.ts
Adds Playwright HEAD fallback suite asserting HEAD responses preserve handler headers (e.g., content-type, x-handler, x-method), prefer GET over ANY, return expected status, and have empty bodies; includes redirect-follow test.
Changelog / Release Note
.changeset/fix-head-request-server-route-fallback.md
Adds a changeset documenting the HEAD fallback behavior change for @tanstack/start-server-core (patch).

Sequence Diagram

sequenceDiagram
    participant Client as Client
    participant Start as StartHandler
    participant Router as Router
    participant File as FileRouteHandler

    Client->>Start: HEAD /path
    Start->>Router: match route & select handler (HEAD → GET → ANY)
    Router->>File: invoke chosen handler
    File-->>Router: Response (status, headers, maybe body)
    Router->>Start: middleware returns Response
    Start-->>Client: Response (same headers/status, body null)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰
I sniff a HEAD and find a GET,
I carry back the headers yet forget the rest.
Redirects hop along their track,
I tuck the body safe—then bounce right back.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and specifically describes the main change: fixing HEAD request handling to fall back to GET handlers per RFC 9110, which is the core objective of this PR.
Linked Issues check ✅ Passed All coding objectives from issue #7270 are met: HEAD falls back to GET (with priority HEAD→GET→ANY), body is stripped while preserving headers/status, redirects are resolved before body stripping, statusText is preserved, and E2E tests verify content-type preservation and handler precedence.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the linked issue: core handler dispatch logic, E2E tests for HEAD behavior, route fixtures, and a changeset. No unrelated modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: Turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get your free trial and get 200 agent minutes per Slack user (a $50 value).


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.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 2, 2026

Bundle Size Benchmarks

  • Commit: 35261948496a
  • Measured at: 2026-05-03T16:35:47.845Z
  • Baseline source: history:35261948496a
  • Dashboard: bundle-size history
Scenario Current (gzip) Delta vs baseline Raw Brotli Trend
react-router.minimal 87.15 KiB 0 B (0.00%) 273.94 KiB 75.70 KiB ▅▅▅▅▅▅▅▅▅▅▅
react-router.full 90.68 KiB 0 B (0.00%) 285.45 KiB 78.71 KiB ▅▅▅▅▅▅▅▅▅▅▅
solid-router.minimal 35.38 KiB 0 B (0.00%) 106.25 KiB 31.81 KiB ▅▅▅▅▅▅▅▅▅▅▅
solid-router.full 40.10 KiB 0 B (0.00%) 120.46 KiB 36.04 KiB ▅▅▅▅▅▅▅▅▅▅▅
vue-router.minimal 53.15 KiB 0 B (0.00%) 151.39 KiB 47.73 KiB ▅▅▅▅▅▅▅▅▅▅▅
vue-router.full 58.28 KiB 0 B (0.00%) 167.56 KiB 52.18 KiB ▅▅▅▅▅▅▅▅▅▅▅
react-start.minimal 101.76 KiB 0 B (0.00%) 322.10 KiB 87.97 KiB ▅▅▅▅▅▅▅▅▅▅▅
react-start.full 105.19 KiB 0 B (0.00%) 332.43 KiB 90.96 KiB ▅▅▅▅▅▅▅▅▅▅▅
react-start.rsbuild.minimal 99.33 KiB 0 B (0.00%) 316.47 KiB 85.46 KiB ▅▅▅▅▅▅▅▅▅▅▅
react-start.rsbuild.full 102.63 KiB 0 B (0.00%) 326.90 KiB 88.28 KiB ▅▅▅▅▅▅▅▅▅▅▅
solid-start.minimal 49.40 KiB 0 B (0.00%) 152.08 KiB 43.60 KiB ▅▅▅▅▅▅▅▅▅▅▅
solid-start.full 55.20 KiB 0 B (0.00%) 168.98 KiB 48.51 KiB ▅▅▅▅▅▅▅▅▅▅▅

Trend sparkline is historical gzip bytes ending with this PR measurement; lower is better.

@@ -931,5 +942,14 @@ async function handleServerRoutes({
pathname,
})

// Strip body from HEAD responses that fell back to the GET handler.
// RFC 9110 §9.3.2: HEAD must send the same headers as GET, but with no body.
if (isHeadFallingBackToGet && ctx.response instanceof Response) {
Copy link
Copy Markdown
Collaborator

@schiller-manuel schiller-manuel May 2, 2026

Choose a reason for hiding this comment

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

the wrapped response does not preserve statusText

better:

return new Response(null, ctx.response)

handlers[requestMethod] ??
handlers['ANY'] ??
(requestMethod === 'HEAD' ? handlers['GET'] : undefined)
isHeadFallingBackToGet =
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

should we strip out the body in case ANY handles the HEAD?

const handler = handlers[requestMethod] ?? handlers['ANY']
// Per RFC 9110 §9.3.2, HEAD should return the same header fields as GET.
// Fall back to the GET handler when no explicit HEAD or ANY handler is defined.
const handler =
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

if both GET and ANY exist, HEAD uses ANY, not GET.

could be solved via:

const handler =
  requestMethod === 'HEAD'
    ? handlers['HEAD'] ?? handlers['GET'] ?? handlers['ANY']
    : handlers[requestMethod] ?? handlers['ANY']

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

add a separate E2E test route for this

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed. Handler selection is now handlers['HEAD'] ?? handlers['GET'] ?? handlers['ANY'], so GET always wins over ANY for HEAD requests.

Added /api/get-and-any with separate GET and ANY handlers, and a test that sends HEAD /api/get-and-any and asserts x-handler: GET.

// Strip body from HEAD responses that fell back to the GET handler.
// RFC 9110 §9.3.2: HEAD must send the same headers as GET, but with no body.
if (isHeadFallingBackToGet && ctx.response instanceof Response) {
return new Response(null, {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A GET-only handler returning redirect({ to: '/login' }) can become a 307 without Location, because handleRedirectResponse() no longer sees isRedirect(response).

either resolve redirects before stripping the body, or strip the body after handleRedirectResponse().

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed. handleRedirectResponse now runs before the body-stripping step, so Location survives.

Added /api/head-redirect-fallback (GET handler returns redirect({ to: '/api/head-fallback', statusCode: 307 })), with a test that sends HEAD and checks the browser can follow the redirect to a 200. If Location were dropped, the browser would stall on the 307 and the assertion would fail.

Also adopted your new Response(null, resolved) suggestion from the other thread. Cleaner.

@nx-cloud
Copy link
Copy Markdown
Contributor

nx-cloud Bot commented May 2, 2026

View your CI Pipeline Execution ↗ for commit 97f09f4

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

☁️ Nx Cloud last updated this comment at 2026-05-03 16:46:53 UTC

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 2, 2026

More templates

@tanstack/arktype-adapter

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

@tanstack/eslint-plugin-router

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

@tanstack/eslint-plugin-start

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

@tanstack/history

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

@tanstack/nitro-v2-vite-plugin

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

@tanstack/react-router

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

@tanstack/react-router-devtools

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

@tanstack/react-router-ssr-query

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

@tanstack/react-start

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

@tanstack/react-start-client

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

@tanstack/react-start-rsc

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

@tanstack/react-start-server

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

@tanstack/router-cli

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

@tanstack/router-core

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

@tanstack/router-devtools

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

@tanstack/router-devtools-core

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

@tanstack/router-generator

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

@tanstack/router-plugin

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

@tanstack/router-ssr-query-core

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

@tanstack/router-utils

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

@tanstack/router-vite-plugin

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

@tanstack/solid-router

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

@tanstack/solid-router-devtools

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

@tanstack/solid-router-ssr-query

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

@tanstack/solid-start

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

@tanstack/solid-start-client

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

@tanstack/solid-start-server

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

@tanstack/start-client-core

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

@tanstack/start-fn-stubs

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

@tanstack/start-plugin-core

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

@tanstack/start-server-core

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

@tanstack/start-static-server-functions

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

@tanstack/start-storage-context

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

@tanstack/valibot-adapter

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

@tanstack/virtual-file-routes

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

@tanstack/vue-router

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

@tanstack/vue-router-devtools

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

@tanstack/vue-router-ssr-query

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

@tanstack/vue-start

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

@tanstack/vue-start-client

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

@tanstack/vue-start-server

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

@tanstack/zod-adapter

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

commit: 5e6b559

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 2, 2026

Merging this PR will not alter performance

✅ 5 untouched benchmarks
⏩ 1 skipped benchmark1


Comparing Zelys-DFKH:fix/head-request-fallback-to-get-handler (5e6b559) with main (3526194)

Open in CodSpeed

Footnotes

  1. 1 benchmark was skipped, so the baseline result was used instead. If it was deleted from the codebase, click here and archive it to remove it from the performance reports.

- HEAD priority is now HEAD -> GET -> ANY (was HEAD -> ANY -> GET)
- body stripping covers ANY fallback, not just GET fallback
- resolve redirects before stripping so Location header is preserved
- copy statusText to the stripped response
- add E2E tests for all three HEAD fallback scenarios
@Zelys-DFKH Zelys-DFKH force-pushed the fix/head-request-fallback-to-get-handler branch from 0f65fbf to 37da897 Compare May 3, 2026 00:15
Copy link
Copy Markdown
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.

♻️ Duplicate comments (1)
packages/start-server-core/src/createStartHandler.ts (1)

944-951: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

instanceof Response guard makes handleRedirectResponse a no-op and silently skips body-stripping for TanStack redirect objects.

Two interconnected effects stem from the instanceof Response guard:

  1. Dead call: redirect() returns a new Redirect object — a plain object, never a native Response. Therefore isRedirect(nativeResponse) is always false for values that satisfy instanceof Response, and handleRedirectResponse returns immediately without doing any redirect resolution in every case this branch is entered. resolved === ctx.response unconditionally.

  2. Missing body-strip for TanStack redirects: When the HEAD-fallback GET/ANY handler returns a TanStack redirect({to: '/login'}), executeMiddleware catches it via isSpecialResponse and stores it in ctx.response as a Redirect object. Because Redirect is not instanceof Response, the body-stripping block at line 944 is skipped entirely and ctx.response falls through to return ctx.response at line 953. The outer handleRedirectResponse at line 774 does correctly resolve it and preserves the Location header, but the resolved response's body is not stripped — a technical RFC 9110 §9.3.2 violation ("server MUST NOT send a message body in the response to HEAD"). In practice redirect bodies are empty (e.g. Response.redirect() produces a null body), so the observable impact is low.

The fix is to drop the instanceof Response guard and let handleRedirectResponse see the TanStack redirect directly:

🛠️ Proposed fix
- if (isHeadFallback && ctx.response instanceof Response) {
-   const resolved = await handleRedirectResponse(ctx.response, request, getRouter)
+ if (isHeadFallback) {
+   const resolved = await handleRedirectResponse(
+     ctx.response as Response,
+     request,
+     getRouter,
+   )
    return new Response(null, {
      status: resolved.status,
      statusText: resolved.statusText,
      headers: resolved.headers,
    })
  }

With this change:

  • For native Response values → handleRedirectResponse early-returns unchanged, body stripped as before. ✓
  • For TanStack redirect() objects → handleRedirectResponse resolves to a proper HTTP Response (preserving Location), then the body is stripped. ✓
  • For undefined → impossible; middleware always sets ctx.response or throws.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/start-server-core/src/createStartHandler.ts` around lines 944 - 951,
The branch that checks "instanceof Response" prevents handleRedirectResponse
from processing TanStack Redirect objects and skipping body-stripping; remove
the instanceof guard so that when isHeadFallback is true you always call await
handleRedirectResponse(ctx.response, request, getRouter) and use its resolved
Response to construct the new Response (preserving resolved.status, statusText,
headers) so redirect objects returned by middleware are resolved and their
bodies get stripped; update the block around isHeadFallback to reference
ctx.response and call handleRedirectResponse unconditionally (retain the same
usage of request and getRouter).
🧹 Nitpick comments (1)
e2e/react-start/server-routes/tests/server-routes.spec.ts (1)

20-71: ⚡ Quick win

The three core HEAD fallback scenarios are well-covered; consider adding a redirect + HEAD test.

Tests 1–3 validate GET fallback, ANY fallback, and GET-over-ANY preference. What's absent is a test for a GET handler that returns a TanStack redirect() (the scenario flagged in the past review comment and the code path guarded by handleRedirectResponse at line 945 of createStartHandler.ts). Due to the instanceof Response bug noted above, a TanStack redirect returned by the HEAD-fallback handler currently skips the body-stripping block entirely. A test exercising that path would make the gap immediately visible.

Suggestion: add a test fixture route (e.g., /api/head-fallback-redirect) whose GET handler returns redirect({ to: '/api/head-fallback', statusCode: 307 }), then assert that HEAD receives a 307 with a Location header and an empty body.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@e2e/react-start/server-routes/tests/server-routes.spec.ts` around lines 20 -
71, Add a new e2e test and fixture route to exercise the GET-redirect + HEAD
fallback path: create an API route (e.g., handler name or path
/api/head-fallback-redirect) whose GET handler returns TanStack's redirect({ to:
'/api/head-fallback', statusCode: 307 }), then add a Playwright test similar to
the other HEAD-fallback tests that does fetch('/api/head-fallback-redirect', {
method: 'HEAD' }) and asserts status === 307, that the Location header points to
/api/head-fallback and that the response body is an empty string; this will
exercise the handleRedirectResponse path in createStartHandler.ts and reveal the
instanceof Response issue noted in the review.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@packages/start-server-core/src/createStartHandler.ts`:
- Around line 944-951: The branch that checks "instanceof Response" prevents
handleRedirectResponse from processing TanStack Redirect objects and skipping
body-stripping; remove the instanceof guard so that when isHeadFallback is true
you always call await handleRedirectResponse(ctx.response, request, getRouter)
and use its resolved Response to construct the new Response (preserving
resolved.status, statusText, headers) so redirect objects returned by middleware
are resolved and their bodies get stripped; update the block around
isHeadFallback to reference ctx.response and call handleRedirectResponse
unconditionally (retain the same usage of request and getRouter).

---

Nitpick comments:
In `@e2e/react-start/server-routes/tests/server-routes.spec.ts`:
- Around line 20-71: Add a new e2e test and fixture route to exercise the
GET-redirect + HEAD fallback path: create an API route (e.g., handler name or
path /api/head-fallback-redirect) whose GET handler returns TanStack's
redirect({ to: '/api/head-fallback', statusCode: 307 }), then add a Playwright
test similar to the other HEAD-fallback tests that does
fetch('/api/head-fallback-redirect', { method: 'HEAD' }) and asserts status ===
307, that the Location header points to /api/head-fallback and that the response
body is an empty string; this will exercise the handleRedirectResponse path in
createStartHandler.ts and reveal the instanceof Response issue noted in the
review.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ba0be7a3-20de-49ae-8923-8f92f12870af

📥 Commits

Reviewing files that changed from the base of the PR and between 0f65fbf88d7bb604fd692815033edb48a8fae164 and 37da897.

📒 Files selected for processing (6)
  • .changeset/fix-head-request-server-route-fallback.md
  • e2e/react-start/server-routes/src/routeTree.gen.ts
  • e2e/react-start/server-routes/src/routes/api/get-and-any.ts
  • e2e/react-start/server-routes/src/routes/api/head-fallback.ts
  • e2e/react-start/server-routes/tests/server-routes.spec.ts
  • packages/start-server-core/src/createStartHandler.ts
✅ Files skipped from review due to trivial changes (3)
  • e2e/react-start/server-routes/src/routes/api/get-and-any.ts
  • .changeset/fix-head-request-server-route-fallback.md
  • e2e/react-start/server-routes/src/routeTree.gen.ts

Zelys-DFKH and others added 3 commits May 2, 2026 19:48
…irect+HEAD E2E test

The `instanceof Response` check before the HEAD body-stripping block was
redundant — `redirect()` returns `new Response(...)` and IS instanceof
Response, and `ctx.response` is always a Response at that point in the
middleware pipeline. Replacing it with an `as Response` cast eliminates
dead branch analysis noise.

Also adds a fourth E2E test: HEAD on a route whose GET handler returns a
`redirect()` must preserve the Location header so the browser can follow it.
The test verifies this by asserting the final status is 200 (meaning the
307 redirect was followed). If the Location header were stripped before the
redirect resolved, the browser would stall on the 307 and the assertion
would fail.
…iewer suggestion

Adopts the tighter form suggested by @schiller-manuel: passing the resolved
Response directly as the ResponseInit arg copies status, statusText, and
headers in one shot instead of spreading them manually.
Copy link
Copy Markdown
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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/start-server-core/src/createStartHandler.ts`:
- Around line 944-950: The current isHeadFallback branch forces ctx.response
through handleRedirectResponse and always wraps its result into new
Response(...), which converts an undefined/absent response into a synthetic 200
OK; change the logic in the isHeadFallback block (the call to
handleRedirectResponse with ctx.response, request, getRouter) to check the
returned value (from handleRedirectResponse) and if it is undefined/null do not
create a new Response—propagate undefined (or return early) instead; update
types so the variable (e.g., resolved) is typed as ResponseInit | undefined and
the code only calls new Response when resolved is a real ResponseInit object.
🪄 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: 25d3f5d5-4beb-4193-b5dd-cd09db55d827

📥 Commits

Reviewing files that changed from the base of the PR and between d9d24f0 and 0d3549e.

📒 Files selected for processing (2)
  • .changeset/fix-head-request-server-route-fallback.md
  • packages/start-server-core/src/createStartHandler.ts
✅ Files skipped from review due to trivial changes (1)
  • .changeset/fix-head-request-server-route-fallback.md

Comment thread packages/start-server-core/src/createStartHandler.ts
Copy link
Copy Markdown
Contributor

@nx-cloud nx-cloud Bot left a comment

Choose a reason for hiding this comment

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

Important

At least one additional CI pipeline execution has run since the conclusion below was written and it may no longer be applicable.

Nx Cloud has identified a possible root cause for your failed CI:

We've identified the failure in tanstack-solid-start-e2e-serialization-adapters:test:e2e as an environment issue unrelated to this PR — the error originates in a pre-built e2e-utils dist artifact (localDummyServer.js) that is missing the users export, and none of our changes touch that package or the solid-start serialization suite. This appears to be a stale CI build artifact that needs to be rebuilt in the environment.

No code changes were suggested for this issue.

You can trigger a rerun by pushing an empty commit:

git commit --allow-empty -m "chore: trigger rerun"
git push

Nx Cloud View detailed reasoning on Nx Cloud ↗


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

Zelys-DFKH and others added 2 commits May 3, 2026 11:28
…fallback

If a fallback GET/ANY handler exits without returning a Response, ctx.response
is undefined. Without the guard, handleRedirectResponse passes undefined through
and new Response(null, undefined) silently synthesizes a 200 OK, masking the
handler bug. Calling throwRouteHandlerError() surfaces the mistake with the same
error used everywhere else in the file. Also removes the unsafe cast -- TypeScript
narrows the type correctly after the never-returning guard.
@schiller-manuel
Copy link
Copy Markdown
Collaborator

thanks for your PR!

@schiller-manuel schiller-manuel merged commit afa40ef into TanStack:main May 3, 2026
17 checks passed
@Zelys-DFKH
Copy link
Copy Markdown
Contributor Author

thanks for your PR!

Thank you for allowing me to contribute! Keep up the great work 🙏

@Zelys-DFKH
Copy link
Copy Markdown
Contributor Author

Thanks for the review and merge!

birkskyum added a commit that referenced this pull request Jun 1, 2026
* fix: republish react-start-rsc dependency chain

* ci: changeset release

* chore: sync published start package versions

* ci: changeset release

* fix publishing

* ci: changeset release

* fix

* ci: apply automated fixes

* ci: changeset release

* refactor: switch router stores to atom get/set API (#7150)

* ci: changeset release

* refactor: shorten internal router store names (#7152)

* ci: changeset release

* chore(types): re-export SearchMiddleware type from react-router (#7087)

* fix(start-plugin-core): reuse deduped server function ids across compilers (#7153)

* ci: changeset release

* fix(router-core): avoid false notFound matches for proxied loader data (#7156)

* fix(router-core): avoid false notFound matches for proxied loader data

* test(react-start): cover proxied loader data notFound regression

* test(react-start): move notFound regression to rsc direct loader

* chore: add changeset

* ci: changeset release

* fix: reduce start SSR manifest asset duplication (#7157)

Co-authored-by: schiller-manuel <schiller-manuel@users.noreply.github.com>
Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>

* ci: changeset release

* docs: fix file extension syntax for prefix/suffix routing examples (#7149)

docs: fix file-based routing examples with literal dots

* chore: bump to h3 v2 rc.20 (#7140)

* ci: changeset release

* chore: stabilize tests (#7159)

* chore: add vite 8 to peer deps (#7160)

Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* ci: changeset release

* chore(start-server-core): remove unnecessary `any` in `getRequestHeaders` (#7164)

* fix(router-generator): harden route file transform rewrites (#7167)

* fix docs (#7168)

* ci: changeset release

* fix(router-plugin): update vite-plugin-solid peer dependency to support version 3.0.0-0 (#7170)

* ci: changeset release

* fix(router-generator): normalize virtual physical subtree paths (#7169)

Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>

* ci: changeset release

* fix: unify virtual module handling for Start Vite plugins (#7178)

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
Co-authored-by: schiller-manuel <schiller-manuel@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>

* ci: changeset release

* fix: add react-server server export for react-start (#7180)

* ci: changeset release

* fix(docs): correct server function name in example (#7173)

* fix react server exports for start and react-router (#7183)

Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>

* chore: stabilize tests (#7185)

* ci: changeset release

* fix(router-core): avoid intermediate success state for async notFound (#7184)

* ci: changeset release

* Add a React Start server-components skill (#7181)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* chore: add sharding for playwright tests (#7187)

* add sharding

* fix dependnancy

* fix playwright shard port reuse

* full bust

* throw more runners into this run

* try to throw money at it and see the effect

* tune

* fix react-router shared route css persistence on nav (#7186)

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* ci: changeset release

* chore: stabilize test (#7192)

* fix(start): include Vite style.css when cssCodeSplit is disabled (#7191)

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* ci: changeset release

* chore: bump solid-js override 1.9.12 (#7202)

* chore: bump query override to 5.99.0 (#7203)

* fix(solid-router): use keyed Show in Outlet to fix child route rendering with useQuery (#7204)

* ci: changeset release

* docs(start): fix authenticated routes doc URL (#7214)

* chore(deps): vitest 4.1.4 (#7212)

* stabilize rsc tests (#7217)

* fix(react-router): prevent webpack static analysis of React.use with let binding (#7182)

* ci: changeset release

* stabilize test (#7220)

* chore: unify react-start basic e2e mode projects (#7206)

* feat(nx): support rsbuild in Playwright inference (#7221)

* test(e2e-rsc): migrate to playwrightModes and dynamic inferred dist (#7222)

* fix(nx): align playwright mode build target naming (#7223)

* docs(start): add missing space after comma in 'Handling requests with a body' (#7234)

* update intent workflow (#7243)

* rsbuild plugin (#7228)

Co-authored-by: neverland <chenjiahan.jait@bytedance.com>
Co-authored-by: Keven Arroyo <dake.3601@gmail.com>

* ci: changeset release

* fix: Split Start plugin core (#7249)

* ci: changeset release

* update intent workflow (#7244)

* fix: asset sorting (#7251)

* ci: changeset release

* chore(deps): update Rsbuild related deps to v2.0.1 (#7245)

* fix actions again? (#7252)

* inline css (#7253)

* ci: changeset release

* fix: do not import 'react-refresh/runtime' (#7255)

Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>

* ci: changeset release

* chore(examples): checkin git outdated route-tree files for react and solid examples (#7257)

* add new bundlesize measurements for rsbuild (#7256)

Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>

* refactor(router-plugin): upgrade unplugin to `v3` (#7258)

* refactor(router-plugin): upgrade unplugin to `v3`

* refactor(start-client-core): use a more explicit typing to `CustomFetch` type

* chore(examples): runtime enforce for needing the `VITE_CONVEX_URL`

* ci: changeset release

* fix: issue 7240 causing fouc (#7250)

* fix: server middleware type in solid-router (#7260)

* replace tsx by jiti (#7261)

Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>

* ci: changeset release

* docs: Fix server function middleware prop (#7262)

* feat(query): add support for custom dehydrate and hydrate options in SSR integration (#7246)

Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* ci: changeset release

* fix: use loader data goes undefined (#7265)

* fix: streaming when using Await component (#7264)

* ci: changeset release

* fix(solid-start): bundle solid-query packages during SSR to fix duplicate QueryClientContext (#6151) (#7267)

* ci: changeset release

* fix(solid-router): hydration mismatch for ssr='data-only' with pendingComponent (#7266)

* docs(router): fix typo in doc (#7268)

* ci: changeset release

* fix(router-core): wildcard nodes respect DFS priority like other nodes in route matching (#7273)

* ci: changeset release

* fix(solid-router): enable route component HMR for Solid

* ci: apply automated fixes

* Revert "ci: apply automated fixes"

This reverts commit 7122f28.

* Revert "fix(solid-router): enable route component HMR for Solid"

This reverts commit b86b061.

* fix(react-start-rsc): re-export renderable types from public entries (#7278)

* fix(react-start-rsc): re-export renderable types from public entries

* changeset - patch

* ci: changeset release

* fix: disabled topLevelVar (#7293)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* ci: changeset release

* fix: fix exports for react-start so useServerFn is available with RSC (#7292)

Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>

* feat: match params (#7263)

* ci: changeset release

* fix(start-plugin-core): sort server fn manifest entries for deterministic build output (#7287)

Co-authored-by: Dor Alagem <doralagem@MacBook-Pro-sl-Dor.local>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Manuel Schiller <meisterpink@gmail.com>

* docs: remove redundant code example from query integration doc (#7298)

* ci: changeset release

* fix: Ignore fully type-only imports and re-exports when collecting im… (#7305)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* ci: changeset release

* feat: `strict: false` for server functions (#7277)

* feat: `strict: false` for server functions

Add a `strict` option to `createServerFn` for type-level server function serialization checks

* feat: `strict: false` for server functions [Self-Healing CI Rerun]

---------

Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>

* ci: changeset release

* fix: parse params union inference (#7306)

* ci: changeset release

* feat: rsc css (#7310)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* ci: changeset release

* fix(router-plugin): isolate route metadata per plugin instance (#7313)

* ci: changeset release

* docs: Improve key differences b/w Start Server Functions and Next.js Server Actions (#7312)

* fix(deps): move fetchdts from devDependencies to dependencies (#7317)

* Revise bug report template for clarity and requirements

Updated the bug report template to clarify the requirements for a reproducer project and modified some labels and descriptions for better clarity.

* ci: changeset release

* chore: fix duplicate "the" typo across router packages (#7323)

* feat: early hints (#7324)

* ci: changeset release

* feat: Link header (#7327)

Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>

* ci: changeset release

* docs(skills): address 8 agent failure modes from user feedback (#7314)

* docs(skills): address 8 agent failure modes from external feedback

Adds new start-core/auth-server-primitives skill (sessions, cookies,
OAuth+PKCE, password-reset enumeration defense, CSRF, rate limiting,
session rotation) and updates 8 existing skills + matching docs to fix
patterns where agents produce insecure or wrong-framework output.

Skill changes:
- new: start-core/auth-server-primitives (server half of auth)
- router-core/auth-and-guards: route guard != RPC guard
- start-core/server-functions: wrong import path, RPC auth required,
  Cache-Control public is a cross-tenant leak, wrong-framework patterns
- start-core/middleware: wrong import path, sendContext shape vs access
  (3-layer wrong/still-wrong/correct), authMiddleware framing
- start-core/execution-model: file markers (server-only/client-only),
  module-level process.env is undefined under Worker SSR
- start-core/deployment: cloudflare env-at-request-time
- router-core/ssr: wrong file structures (next.js, react-router-dom)
- router-core/type-safety: wrong-framework imports + structures

Docs updated to mirror each skill change so source-of-truth and the
intent-indexed skill stay in sync. New authentication-server-primitives
guide is the long-form companion to the new skill.

intent validate: 30 skill files pass (was 29).

* ci: apply automated fixes

* docs(skills): address coderabbit review feedback

- Fix internal docs links to use correct relative paths instead of an
  absolute /start/latest/... URL and missing one ../ segment
- Remove blank line inside auth-and-guards blockquote (markdownlint MD028)
- Restore overload pattern in type-safety ValidateNavigateOptions and
  ValidateRedirectOptions examples; the casts I had introduced stripped
  generic context and contradicted the skill's own no-cast rule
- Add db.sessions.revokeAllForUser before create in login rotation
  snippets so the example matches the prose
- Soften useServerFn guidance: it's required only when the server
  function throws redirect/notFound; plain-data calls work directly and
  via useMutation/useQuery

* ci: apply automated fixes

* docs(skills): compress type-safety to stay under 500-line cap

Prettier's autofix expanded my single-line overload signatures across
multiple lines, pushing the file over the 500-line limit. Drop the
redundant fetchOrRedirect example (same pattern as useDelayedNavigate)
and describe ValidateRedirectOptions usage in prose instead.

* docs(skills): CSRF origin check should compare full origin, not host alone

Comparing only new URL(origin).host against APP_HOST silently accepts a
mismatched scheme — http://example.com would pass a check meant for
https://example.com. Compare the full origin (scheme + host + port)
against APP_ORIGIN instead. Same fix in skill and docs.

* docs(skills): make useDelayedNavigate callback truly return void

The callback returned the result of setTimeout (a timer handle), not
void as the public overload's return type implied. Wrap in a block so
the example matches the declared return type.

Skipped the related nitpick to add a separate redirect example — the
existing prose already describes the same overload pattern, and a
duplicate example would push the file close to the 500-line cap that
prettier autofix has been bumping us against.

* docs(skills): fix two real bugs in auth-server-primitives examples

1. Cookie parser truncated values containing '='. Signed cookies, JWTs,
   and base64-padded values all use '='. Use indexOf to split on the
   FIRST '=' only.

2. Login example short-circuited verifyPasswordHash on user-not-found,
   contradicting the prose's "same time, same error" claim — the
   no-user branch returned instantly while wrong-password spent ~100ms
   hashing, leaking account existence over the wire. Always verify
   against a hash; use a precomputed DUMMY_PASSWORD_HASH when the user
   is missing, then combine with the user-exists bit for the final ok.

Same fixes in the SKILL.md and the docs companion.

* docs(skills): address manuel's review on react-specific guides

- middleware.md, server-functions.md: drop cross-framework <framework>
  placeholders; this is the React-specific guide, just say
  @tanstack/react-start
- execution-model.md: drop the same trailing line about solid-start /
  vue-start paths
- hosting.md: remove the Cloudflare env-handling subsection — the
  general per-request rule lives in environment-variables.md and
  doesn't need to be repeated under a specific host
- environment-variables.md: mention the cloudflare:workers env binding
  as the canonical Cloudflare way to read env (including module scope),
  per Manuel's link to the Cloudflare docs
- deployment skill: same upgrade — show the cloudflare:workers env
  pattern alongside the per-request handler approach

* docs(skills): drop redundant server-only marker in session example

The file already imports from @tanstack/react-start/server, which is
on import protection's default client-deny specifier list. The
side-effect marker is redundant — drop it. Same fix in skill and docs.

* docs(skills): drop wrong-import-path mistakes — TS already catches them

Manuel pointed out that TypeScript catches both common wrong paths:
'@tanstack/react-router' has no exported member createServerFn /
createMiddleware, and '@tanstack/start' is "Cannot find module". Skill
space is precious; the items don't earn their slot if tsc handles them.

Removed:
- Common Mistake "Wrong import path" from server-functions and
  middleware skills (renumbered the remaining mistakes)
- The matching top-of-file CRITICAL line in both skills
- The "Import path" callouts in the middleware and server-functions
  docs

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* remove old intent artifacts (#7333)

* fix(start-server-core): fall back to GET handler for HEAD requests (RFC 9110 §9.3.2) (#7325)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* ci: changeset release

* test: add reproducer for #2514 (#7336)

* test: reproducer for #2547 (#7337)

* fix: fix plain TypeScript parser handling (#7342)

* ci: changeset release

* fix: disable rsbuild server compression (#7348)

* fix: update deps (#7340)

* ci: changeset release

* update bundlesize benchmark (#7356)

* fix: Bump jiti to 2.7.0 (#7355)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com>

* ci: apply automated fixes

* ci: changeset release

* Document server function strict serialization options (#7358)

* Document server function strict option

Agent-Logs-Url: https://github.com/TanStack/router/sessions/8deabe7a-7412-455e-9111-97a13cb4582e

Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com>

* Refine strict docs wording

Agent-Logs-Url: https://github.com/TanStack/router/sessions/e2857d6e-314e-496c-b99b-78c207c28c77

Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com>

* feat(start): CSRF middleware (#7373)

* fix(router-core): fix missing closing paren in CSS.supports check for view transition types (#7369)

* fix: fix jiti usage for tsconfig paths (#7382)

* Enable jiti tsconfig path aliases

Agent-Logs-Url: https://github.com/TanStack/router/sessions/0a481c9b-eb97-4543-acc5-71d43b97d386

Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com>

* Use fixture for jiti tsconfig aliases

Agent-Logs-Url: https://github.com/TanStack/router/sessions/182b9baa-9e54-4813-a322-c33a1da5417d

Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com>

* Track fixture path alias helper

Agent-Logs-Url: https://github.com/TanStack/router/sessions/182b9baa-9e54-4813-a322-c33a1da5417d

Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com>

* Add router-generator changeset

Agent-Logs-Url: https://github.com/TanStack/router/sessions/ab1a42cc-7326-4e36-a656-f01179221cee

Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com>

* Format virtual config fixture

Agent-Logs-Url: https://github.com/TanStack/router/sessions/22194166-b3a7-431e-b723-ad594d4b0405

Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com>

* Update bundle-size.yml

* Update labeler.yml

* Update bundle-size.yml

* ci: add pinGitHubActionDigests (#7387)

* chore(deps): pin dependencies (#7388)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>

* minor semver bump to all packages (#7395)

* ci: zizmor (#7389)

* chore(pnpm): update pnpm to v11 (#7392)

* chore: add CODEOWNERS file (#7394)

* chore: add CODEOWNERS file

* chore: add Nx and NPMRC

* Update .github/CODEOWNERS

---------

Co-authored-by: Nicolas Beaussart <nic.beaussart@gmail.com>

* fix: revert plugin changes, createCsrfMiddleware compilation, fix HMR tests (#7400)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Manuel Schiller <manuel.schiller@caligano.de>

* ci: align release workflow to query (#7404)

* ci: Version Packages (#7405)

ci: changeset release

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* feat(start): add inline CSS runtime controls and asset URL templates (#7380)

* ci: Version Packages (#7407)

* fix: Fix literal underscore paths under pathless layouts (#7408)

* ci: Version Packages (#7409)

ci: changeset release

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* feat(router-core): params.priority route option as tie breaker in matching algorithm (#7411)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* ci: Version Packages (#7413)

* fix(router-core): hydrate before initial client route match (#7416)

* ci: Version Packages (#7417)

* fix(router-plugin): detect typed root route context for HMR (#7420)

* ci: Version Packages (#7421)

* fix: fix route mismatch warnings and HMR route indexes (#7422)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* ci: Version Packages (#7423)

* security: stricter pnpm config blockExoticSubdeps & trustPolicy (#7425)

* docs(start): use router package for module declaration to type the request context (#7427)

* feat: deferred hydration (#7362)

* feat: deferred hydration

* fix

* tests

* solid tests

* Changes before error encountered

Agent-Logs-Url: https://github.com/TanStack/router/sessions/5263c469-75c2-4470-bd4c-86f9b43964f4

Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com>

* chore: address hydration review follow-ups

Agent-Logs-Url: https://github.com/TanStack/router/sessions/16e27113-ff01-4de8-aded-b9be9f6dd4ff

Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com>

* fix(start-client-core): correct import order in hydrateStart.ts

Co-authored-by: schiller-manuel <schiller-manuel@users.noreply.github.com>

* chore: remove tracked nx self-healing artifacts

Agent-Logs-Url: https://github.com/TanStack/router/sessions/95750760-1348-437c-8f73-cc45e899003a

Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com>
Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>
Co-authored-by: schiller-manuel <schiller-manuel@users.noreply.github.com>

* chore: update @swc/core in example/react/quickstart-webpack-file-based (#7434)

* chore: update @swc/core in example/react/quickstart-webpack-file-based

* chore: update @swc/core in example/react/quickstart-webpack-file-based [Self-Healing CI Rerun]

---------

Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>

* docs(start): compare deferred hydration to Astro islands (#7438)

Adds a short mental-model section answering the common question
about how TanStack Start's deferred hydration relates to Astro
islands.

* docs(start): compare deferred hydration to React selective hydration (#7442)

Adds a short comparison section answering the common question about how
TanStack Start's deferred hydration relates to React 18's selective
hydration. The framing: selective hydration controls the order of
inevitable hydration work; deferred hydration controls whether and when
that work happens at all.

* chore: update chokidar to v5 (#7439)

* chore: update @rolldown/pluginutils to 1.0.1 (#7440)

* chore: update zod to v4.4.3 (#7441)

* chore: update zod to v4.4.3

* fix(start): preserve route path defaults

* fix(examples): resolve zod 4 build failures

* chore: update express and webpack-dev-server (#7443)

* chore: update express to v5.2.1

* chore: update webpack-dev-server to v5.2.4

* ci: Version Packages (#7435)

ci: changeset release

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* chore: ignore nx generated folders (#7451)

* perf: optimize and test rewrite (#7448)

optimize and test rewrite

* fix: fix scroll restoration issues (#7447)

Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>

* ci: Version Packages (#7452)

* fix: Fix escaped underscore index route generation (#7453)

* ci: Version Packages (#7454)

* ci: fix release notes diff range after Release PR flow (#7456)

* fix(start): explicitly re-export public API to survive SSR cold-start cycle (#7466)

* fix: Fix hash scrolling with `resetScroll={false}` (#7464)

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* chore: enforce pnpm 11 (#7465)

* ci: Version Packages (#7467)

* chore: only run autofix on PRs (#7469)

* feat(start): support rsbuild iife client output (#7477)

* ci: Version Packages (#7478)

* fix: bundled dev support for vite (#7482)

* ci: Version Packages (#7483)

* fix(start): avoid encoded virtual adapter ids in vite dev (#7484)

* fix release (#7487)

* ci: Version Packages (#7485)

* chore: migrate changesets changelog generator (#7490)

* fix: Fix Hydrate re-exports to avoid circular HMR updates (#7492)

* ci: Version Packages (#7493)

* fix(start): emit boot-sibling chunks as scripts for IIFE entries (#7501)

Co-authored-by: Keven Arroyo <kevenarroyo@microsoft.com>

* ci: Version Packages (#7502)

* chore: stabilize tests (#7503)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* fix: fix streaming (#7497)

* ci: Version Packages (#7504)

ci: changeset release

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* ci: update all actions (#7506)

* ci: update all actions

* disable package manager cache

* fix: fix primitive beforeLoad errors (#7505)

* fix: fix primitive beforeLoad errors

* ci: apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* ci: Version Packages (#7508)

* feat(rsbuild): add RSC support (#7509)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* ci: Version Packages (#7513)

* fix(solid): resolve Solid 2 merge issues

* ci: apply automated fixes

* use v2 query

* fix solid v2 imports

* solid v2 port of new e2e

* solid v2

* nxignore solid v1 peer deps

* use "@rsbuild/plugin-solid": "^2.0.0-beta.0",

* fix hydrationscript

* add nohydration

* remove early return

* fix: solid-start hydration

* fix: update createEffect to return true for hydration signals

* remove nxignore

* add back nxignore for 3rdparty deps

* $_TSR stub to fix serialization tests

* Revert "$_TSR stub to fix serialization tests"

This reverts commit ef802e9.

* fix: update solid selective ssr links

* fix: stream solid Await fallback

* align solid-start basic by removing test:e2e

* remove unusese build:prerender build:spa

* fix: clean up solid hydrate fallback dom

* fix: resolve solid wrapper children

* fix: stabilize serialization stream e2e test

* fix: keep SSR globals through document parse

* html standard mode

* clean

* fix: pass solid ssr manifest

* use await fallback

---------

Co-authored-by: Tanner Linsley <tannerlinsley@gmail.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Manuel Schiller <manuel.schiller@caligano.de>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Flo <fpellet@ensc.fr>
Co-authored-by: James Howard <james@reetgood.co.uk>
Co-authored-by: schiller-manuel <schiller-manuel@users.noreply.github.com>
Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com>
Co-authored-by: Mohamed Khaled <mohamedkhaled012@yahoo.com>
Co-authored-by: Birk Skyum <74932975+birkskyum@users.noreply.github.com>
Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Ulrich Stark <github@ustark.de>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
Co-authored-by: MoonBrillante <32852571+MoonBrillante@users.noreply.github.com>
Co-authored-by: Coding Cossack <108333654+CodingCossack@users.noreply.github.com>
Co-authored-by: Nicolas Beaussart <nic.beaussart@gmail.com>
Co-authored-by: Pavan Shinde <pavann97@gmail.com>
Co-authored-by: mixelburg <52622705+mixelburg@users.noreply.github.com>
Co-authored-by: Mukunda Rao Katta <mukunda.vjcs6@gmail.com>
Co-authored-by: Sarah Gerrard <gerrardsarah@gmail.com>
Co-authored-by: neverland <chenjiahan.jait@bytedance.com>
Co-authored-by: Keven Arroyo <dake.3601@gmail.com>
Co-authored-by: Sean Cassiere <33615041+SeanCassiere@users.noreply.github.com>
Co-authored-by: Abhishek Raj <abhi@raj.me>
Co-authored-by: Dominik Dorfmeister 🔮 <office@dorfmeister.cc>
Co-authored-by: Birk Skyum <birk.skyum@pm.me>
Co-authored-by: Keven Arroyo <kevenarroyo@microsoft.com>
Co-authored-by: Dor Alagem <dor3382@gmail.com>
Co-authored-by: Dor Alagem <doralagem@MacBook-Pro-sl-Dor.local>
Co-authored-by: Manuel Schiller <meisterpink@gmail.com>
Co-authored-by: Franklin Shera <fshera96@gmail.com>
Co-authored-by: Tom Smithhisler <tomsmithhisler@gmail.com>
Co-authored-by: dfedoryshchev <64079946+dfedoryshchev@users.noreply.github.com>
Co-authored-by: Sarah Gerrard <hello@sarahgerrard.me>
Co-authored-by: Zelys <zelys@dfkhelper.com>
Co-authored-by: Shkumbin Hasani <34962865+shkumbinhasani@users.noreply.github.com>
Co-authored-by: Lachlan Collins <1667261+lachlancollins@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Harry Whorlow <79278353+harry-whorlow@users.noreply.github.com>
Co-authored-by: Corbin Crutchley <git@crutchcorn.dev>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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.

HEAD requests to server routes return text/html instead of handler's content-type

2 participants