Skip to content

Start dev server can return app HTML for internal Vite assets on LAN/IP access when Sec-Fetch-Dest is missing #7134

@Neonsy

Description

@Neonsy

Which project does this relate to?

Start

Describe the bug

In TanStack Start dev mode, accessing the same valid page through a LAN/IP URL can break hydration even though the route itself is valid and SSR renders correctly

Your Example Website or App

https://github.com/Neonsy/tanstack-start-lan-dev-repro

Steps to Reproduce the Bug or Issue

I reproduced this on a minimal standalone app that keeps one valid token route:

  • /feedback/dev-test

Invalid token routes intentionally return 404, so this is not caused by an invalid route

In the failing LAN case, hydration-dependent UI stops behaving correctly
In the repro that shows up as:

  • required progress staying stale
  • the optional textarea counter not live-updating
  • jump-to-next-missing not focusing the intended control

I narrowed this down to internal Vite dev asset requests falling through into Start's HTML handler when Sec-Fetch-Dest is missing
This does not appear to be app-specific state logic

Related observation from the original private app:

  • importing CSS as a URL, for example import stylesheetUrl from "./styles.css?url", also behaved differently
  • that variant worked on localhost
  • the same import path did not behave correctly on the LAN/IP URL
  1. Clone the repro and install dependencies with pnpm install
  2. Run pnpm dev:broken
  3. Open http://localhost:3000/feedback/dev-test
  4. Open the LAN/IP URL shown by Vite, for example http://192.168.100.27:3000/feedback/dev-test
  5. On both pages:
    • click the next-missing button
    • answer both required questions
    • type in the optional textarea
  6. Compare the behavior

Expected behavior

TanStack Start dev mode should hydrate correctly whether the app is opened through localhost or through a LAN/IP URL

Internal Vite dev asset requests should not fall through into Start's HTML handler, even if the browser or network path does not provide Sec-Fetch-Dest

Screenshots or Videos

No response

Platform

  • Router / Start Version:
    • @tanstack/react-router@1.168.10
    • @tanstack/react-start@1.167.16
  • OS: Windows
  • Browser: Helium (Chromium-based browser)
  • Browser Version: 0.10.8.1
  • Bundler: Vite
  • Bundler Version: 8.0.7
  • Nitro: 3.0.1-20260402-182549-a5a3389c

Additional context

The original app that led to this investigation is private
The repro linked above is a public-safe standalone app that preserves only the abstract symptom pattern

What the repro proves on my machine:

  • broken mode:
    • localhost passes
    • LAN/IP fails
    • vite/dist/client/env.mjs returns 404 text/html on the LAN path
  • patched mode:
    • localhost passes
    • LAN/IP passes
    • the same internal request returns a JavaScript module response

The workaround is toggleable in vite.config.ts and only applies in dev mode when REPRO_PATCH=1

When enabled, it forces:

  • req.headers["sec-fetch-dest"] = "script"

for obvious internal module requests when that header is missing, including:

  • /@vite/client
  • /@react-refresh
  • /@vite/env
  • /@id/*
  • /src/*.(css|js|ts|tsx|mjs|cjs|mts|cts)
  • /node_modules/* with those extensions

Reverting that workaround makes the LAN URL fail again
Restoring it makes the LAN URL work again

Additional signal from the original private app

  • importing CSS as a URL with ?url, for example import stylesheetUrl from "./styles.css?url", worked on localhost
  • the same pattern did not work correctly on the LAN/IP URL

That made me suspect the issue is not limited to one specific form component or one specific module path, but is tied more generally to how dev asset requests are handled on the LAN/IP path

My current suspicion is that this is a TanStack Start dev-server integration issue around internal Vite asset handling when Fetch Metadata headers are missing on LAN/IP access

Note

The investigation has been assisted with AI, but only that

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions