Skip to content

loadAndTransform regression in 8.0.4: consumer === "server"` bypass removed, breaks Deno + nitro #22237

@nestarz

Description

@nestarz

Describe the bug

Vite version: 8.0.3 → 8.0.4 (regression)

What broke

In loadAndTransform (dist/node/chunks/node.js), 8.0.3 had:

if (environment.config.consumer === "server" || isFileLoadingAllowed(environment.getTopLevelConfig(), slash(file))) {
    code = await fsp.readFile(file, "utf-8");

8.0.4 removed the consumer === "server" short-circuit:

if (options.skipFsCheck || isFileLoadingAllowed(environment.getTopLevelConfig(), slash(file))) {
    code = await fsp.readFile(file, "utf-8");

When no plugin handles the load and the file path fails isFileLoadingAllowed, code stays null and the function throws:

Error: Failed to load url .../dev-entry.mjs (...). Does the file exist?

The file exists. It is never read.

Why isFileLoadingAllowed rejects it — root cause

This is a two-part failure.

1. searchForWorkspaceRoot does not recognise deno.json

Vite only looks for pnpm-workspace.yaml or lerna.json as workspace markers. It does not recognise deno.json.

In a Deno workspace, the repo root carries a deno.json that declares workspace members, and deno install places all npm packages under <repo-root>/node_modules/.deno/<pkg@version>/. But because Vite doesn't know about deno.json, searchForWorkspaceRoot returns the sub-package directory (e.g. packages/playground) rather than the actual repo root.

Vite therefore sets:

server.fs.allow = ["<repo-root>/packages/playground"]

But the module that needs to be loaded lives at:

<repo-root>/node_modules/.deno/[email protected]/node_modules/nitro/dist/runtime/internal/vite/dev-entry.mjs

That path is outside server.fs.allow.

2. The consumer === "server" bypass was removed in 8.0.4

In 8.0.3, server-consumer environments bypassed isFileLoadingAllowed entirely, so the allow-list miscalculation had no effect. Removing the bypass in 8.0.4 exposed it.

Concrete failure

Nitro's vite plugin creates a nitro environment (consumer: "server") and spawns a worker thread that loads dev-entry.mjs via ModuleRunner. The runner sends a fetchModule RPC to the vite server, which calls loadAndTransform. That call rejects the path → code is nullERR_LOAD_URL:

Error: Failed to load url /project/node_modules/.deno/[email protected]/node_modules/nitro/dist/runtime/internal/vite/dev-entry.mjs
  code: 'ERR_LOAD_URL',
  runnerError: Error: RunnerError
      at reviveInvokeError (vite/dist/node/module-runner.js:539)
      at ModuleRunner.getModuleInformation (vite/dist/node/module-runner.js:1187)
      at EnvRunner.reload (nitro/dist/runtime/internal/vite/node-runner.mjs:49)

Workaround

Pin vite to 8.0.3.

Expected behavior

Either:

  • searchForWorkspaceRoot recognises deno.json so fs.allow covers <repo-root>/node_modules/; or
  • Server-consumer environments (consumer: "server") can load any file from disk without being gated by isFileLoadingAllowed, as they were in 8.0.3.

Reproduction

https://github.com/nestarz/vite-deno-loadandtransform-issue

Steps to reproduce

No response

System Info

System:
    OS: macOS 26.x
    CPU: (8) arm64
    Memory: 60.25 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.20.0 - /Users/x/.version-fox/temp/1776117600-43036/nodejs/bin/node
    Yarn: 1.22.22 - /Users/x/.version-fox/temp/1776117600-43036/nodejs/bin/yarn
    npm: 10.9.3 - /Users/x/.version-fox/temp/1776117600-43036/nodejs/bin/npm
    pnpm: 9.15.0 - /Users/x/.version-fox/temp/1776117600-43036/nodejs/bin/pnpm
    Deno: 2.7.11 - /Users/x/.version-fox/temp/1776117600-43036/deno/deno

Used Package Manager

npm

Logs

No response

Validations

Metadata

Metadata

Assignees

No one assigned

    Labels

    p2-edge-caseBug, but has workaround or limited in scope (priority)

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions