`experimental.bundledDev`: `hotUpdate` runs without environment injection (`this.environment` undefined), leaving stale output until restart
Describe the bug
Under experimental.bundledDev, a plugin's hotUpdate hook is invoked with this.environment undefined. Reading this.environment is the documented way to scope hotUpdate behavior (https://vite.dev/changes/hotupdate-hook), so plugins following the docs throw a TypeError on every file edit.
Mechanism, as far as we can tell from the source (checked on main and v8.1.5):
ROLLUP_HOOKS(packages/vite/src/node/constants.ts) includeswatchChangebut nothotUpdate.injectEnvironmentToHooks(packages/vite/src/node/build.ts) wrapsresolveId/load/transformexplicitly and every other hook onlyif (ROLLUP_HOOKS.includes(hook))— so no environment-bound wrapper exists forhotUpdate, and under bundled dev the hook executes with the engine's bare plugin context.
The consequence is worse than a crash: the throw is captured as a build error, the dev server keeps running, and it serves stale output on every subsequent edit until restart. (#23024 improved terminal printing for failed HMR updates, but the hook-contract violation and the stale serving remain.) For anyone running Vite behind a wrapper — hosted dev servers, CI preview environments — this presents as "HMR silently stopped working."
Real-world occurrence: @tanstack/start-plugin-core reads this.environment.name on the first line of its hotUpdate hook (plugin.ts) — deterministic breakage on @tanstack/start-plugin-core 1.171.17–1.171.34, tracked in TanStack/router#8062 (guard PR TanStack/router#8061). These versions are pulled transitively by current @tanstack/react-start releases, so the blast radius is every TanStack Start app trying bundled dev.
Related issues, which we believe are distinct facets of the same underlying gap:
- #23125 — the
hotUpdateoptions object missingserver/timestamp/read(this issue is about thethiscontext instead). - #23124 (closed, Phase 2 milestone).
- #22956 — the open PR adding a
hotUpdateadapter for bundled dev, which presumably becomes the real fix. This issue is about the behavior of current releases until it lands.
Suggested behavior until #22956 lands (in order of preference)
- Bind the environment for
hotUpdatewhen plugins are handed to the full-bundle dev engine, even while the Phase 2 semantics (#22746) are still being designed. - Or skip
hotUpdatehooks entirely under bundled dev, with a one-time warning naming the plugin — an explicitly unsupported hook should not run with a context that violates its documented contract. - At minimum, make the failure loud and attributed, rather than degrading to stale serving.
Reproduction
https://github.com/TIMTOMTOP/tanstack-hotupdate-repro
Steps to reproduce
npm install && npm run dev(repro pins[email protected],@tanstack/[email protected]→@tanstack/[email protected])- Set
experimental: { bundledDev: true }(already set in the repro config) - Edit any source file
hotUpdatethrowsTypeError: Cannot read properties of undefined (reading 'name'); the error is captured as a build error and the dev server serves stale output for all subsequent edits until restart
System Info
vite: 8.2.1 (also verified the ROLLUP_HOOKS omission on v8.1.5 and main)
@tanstack/react-start: 1.168.44 (→ @tanstack/start-plugin-core 1.171.34)
See reproduction repository for the full manifest.
Used Package Manager
npm
Validations
- Follow our Code of Conduct
- Read the Contributing Guidelines.
- Read the docs.
- Check that there isn't already an issue that reports the same bug to avoid creating a duplicate. (Closest are #23125 / #23124 — different facets, cross-linked above.)
- Make sure this is a Vite issue and not a framework-specific issue.
- Check that this is a concrete bug.
- The provided reproduction is a minimal reproducible example of the bug.
Source: vitejs/vite