Affected versions: vite 8.0.4 – 8.0.8
Works on: vite 8.0.3
Context: Deno workspace with a sub-package using @jsr/bureaudouble__deno-vite-plugin + nitro/vite
deno install # installs packages at workspace root (not inside app/)
cd app
deno task dev
# → Error: Failed to load url .../node_modules/.deno/nitro@3.0.1-alpha.2/.../dev-entry.mjs. Does the file exist?To confirm 8.0.3 works, change "vite": "8.0.8" → "vite": "8.0.3" in app/package.json,
re-run deno install from the workspace root, then deno task dev from app/ → starts cleanly.
Error: Failed to load url /path/node_modules/.deno/nitro@3.0.1-alpha.2/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)
The file exists. Vite fails to read it.
This is a two-part issue:
1. Vite's searchForWorkspaceRoot does not recognise deno.json
Vite looks for pnpm-workspace.yaml or lerna.json to find the workspace root
(source).
It does not look for deno.json.
In a Deno workspace, the repo root contains a deno.json that declares workspace members.
deno install installs all npm packages under <workspace-root>/node_modules/.deno/<pkg@version>/.
But because Vite does not recognise deno.json, searchForWorkspaceRoot returns the sub-package
directory (e.g. app/) as the workspace root, not the actual repo root.
Vite therefore sets:
server.fs.allow = ["<repo-root>/app"]
The nitro dev-entry.mjs lives at:
<repo-root>/node_modules/.deno/nitro@3.0.1-alpha.2/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 vite 8.0.4
In loadAndTransform (dist/node/chunks/node.js):
// vite 8.0.3
if (environment.config.consumer === "server" || isFileLoadingAllowed(environment.getTopLevelConfig(), slash(file))) {
code = await fsp.readFile(file, "utf-8");// vite 8.0.4+
if (options.skipFsCheck || isFileLoadingAllowed(environment.getTopLevelConfig(), slash(file))) {
code = await fsp.readFile(file, "utf-8");The consumer === "server" bypass let nitro's ModuleRunner (running in a worker thread)
load any file unconditionally. Its removal means isFileLoadingAllowed now gates all loads —
including for server-consumer environments. When the allow list is wrong (see part 1),
code stays null and vite throws ERR_LOAD_URL.
Either:
searchForWorkspaceRootshould recognisedeno.jsonworkspace roots, sofs.allowcovers<repo-root>/node_modules/; or- Server-consumer environments (
consumer: "server") should still be able to load any file from disk, as they were in 8.0.3.