From 82a279cc79d4cf6c3ebf04f036caa7eef5d2ce54 Mon Sep 17 00:00:00 2001 From: dasilvaluis <15066801+dasilvaluis@users.noreply.github.com> Date: Sat, 3 Oct 2026 20:23:08 +0300 Subject: [PATCH] fix(nitro): Use forward slashes for resolved plugin paths on Windows `createResolver` returned `node:path` results, so on Windows the server plugin was registered as `C:\Users\...\runtime\plugins\server`. Nitro writes plugin paths verbatim into the generated `#nitro/virtual/plugins` module (`import _x from ""`), where the backslashes are read as escape sequences, so the import becomes `C:Users...` and both `vite dev` and `vite build` fail with ERR_MODULE_NOT_FOUND / "failed to resolve import". Nitro's own plugin paths come from `pathe` and are unaffected. Normalize the resolved path to forward slashes, which resolve on every platform. Co-Authored-By: Claude Opus 5.5 (1M context) --- packages/nitro/src/utils/resolver.ts | 5 ++++- packages/nitro/test/resolver.test.ts | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 packages/nitro/test/resolver.test.ts diff --git a/packages/nitro/src/utils/resolver.ts b/packages/nitro/src/utils/resolver.ts index f0bde304d929..0b1f311cef65 100644 --- a/packages/nitro/src/utils/resolver.ts +++ b/packages/nitro/src/utils/resolver.ts @@ -20,6 +20,9 @@ export function createResolver(base: string): Resolver { } return { - resolve: (...path) => resolve(resolvedBase, ...path), + // Nitro writes plugin paths verbatim into a generated `import "…"` statement, where the + // backslashes of a Windows path read as escape sequences (`C:\Users` becomes `C:Users`). + // Forward slashes resolve on every platform, so normalize to them. + resolve: (...path) => resolve(resolvedBase, ...path).replace(/\\/g, '/'), }; } diff --git a/packages/nitro/test/resolver.test.ts b/packages/nitro/test/resolver.test.ts new file mode 100644 index 000000000000..6db133774126 --- /dev/null +++ b/packages/nitro/test/resolver.test.ts @@ -0,0 +1,16 @@ +import { describe, expect, it } from 'vitest'; +import { createResolver } from '../src/utils/resolver'; + +describe('createResolver', () => { + it('resolves relative to the directory of a file URL', () => { + const resolver = createResolver(import.meta.url); + + expect(resolver.resolve('../src/utils/resolver.ts')).toMatch(/packages\/nitro\/src\/utils\/resolver\.ts$/); + }); + + it('never returns backslashes, so the path survives being written into an import string', () => { + const resolver = createResolver(import.meta.url); + + expect(resolver.resolve('../runtime/plugins/server')).not.toContain('\\'); + }); +});