-
-
Notifications
You must be signed in to change notification settings - Fork 34.9k
Description
Version
v24.12.0
Platform
Microsoft Windows NT 10.0.26200.0 x64
Subsystem
No response
What steps will reproduce the bug?
I ran into this while running pnpm dev in a project with a deep node_modules path:
TypeError: Package import specifier "#module-sync-enabled" is not defined imported from
C:\Users\...\node_modules\.pnpm\@react-router+dev@7.13.0_...\@react-router\dev\module-sync-enabled\index.mjs
Minimal repro — save as test.mjs and run with node test.mjs on Windows (with LongPathsEnabled):
import fs from "node:fs";
import { createRequire } from "node:module";
import path from "node:path";
// \\?\ prefix bypasses MAX_PATH limit for Win32 file APIs
const lp = (p) => "\\\\?\\" + p;
const ok = (fn) => {
try { fn(); return "OK"; }
catch (e) { console.error(e); return "FAIL"; }
};
const MAX = 259; // MAX_PATH (260) minus null terminator
const cwd = process.cwd();
const fixedLen = cwd.length + 2 + "package.json".length;
const results = {};
for (const target of [MAX, MAX + 1]) {
const dir = path.join(cwd, "a".repeat(target - fixedLen));
const dep = path.join(dir, "node_modules", "dep");
fs.mkdirSync(lp(dep), { recursive: true });
fs.writeFileSync(
lp(path.join(dir, "package.json")),
JSON.stringify({ imports: { "#foo": "./foo.mjs" } }),
);
fs.writeFileSync(lp(path.join(dir, "foo.mjs")), "export default 1\n");
fs.writeFileSync(
lp(path.join(dep, "package.json")),
JSON.stringify({ name: "dep", exports: { ".": "./index.mjs" } }),
);
fs.writeFileSync(lp(path.join(dep, "index.mjs")), "export default 1\n");
const { resolve } = createRequire(path.join(dir, "_.mjs"));
results[`${target} chars`] = {
"fs.access": ok(() => fs.accessSync(lp(path.join(dir, "package.json")))),
'resolve("dep")': ok(() => resolve("dep")),
'resolve("#foo")': ok(() => resolve("#foo")),
};
fs.rmSync(lp(dir), { recursive: true, force: true });
}
console.table(results);How often does it reproduce? Is there a required condition?
Always reproduces when the package.json path is >= 260 characters. Requires Windows with LongPathsEnabled set (so that other file operations work fine past MAX_PATH).
Common with deeply nested node_modules (e.g. pnpm .pnpm layout + tools that create deep directories like .claude/worktrees).
What is the expected behavior? Why is that the expected behavior?
All three operations should succeed at both path lengths:
┌───────────┬───────────┬────────────────┬─────────────────┐
│ (index) │ fs.access │ resolve("dep") │ resolve("#foo") │
├───────────┼───────────┼────────────────┼─────────────────┤
│ 259 chars │ 'OK' │ 'OK' │ 'OK' │
│ 260 chars │ 'OK' │ 'OK' │ 'OK' │
└───────────┴───────────┴────────────────┴─────────────────┘
LongPathsEnabled is set and both fs operations and subpath exports (which also resolve through package.json) work fine past MAX_PATH.
What do you see instead?
┌───────────┬───────────┬────────────────┬─────────────────┐
│ (index) │ fs.access │ resolve("dep") │ resolve("#foo") │
├───────────┼───────────┼────────────────┼─────────────────┤
│ 259 chars │ 'OK' │ 'OK' │ 'OK' │
│ 260 chars │ 'OK' │ 'OK' │ 'FAIL' │
└───────────┴───────────┴────────────────┴─────────────────┘
TypeError [ERR_PACKAGE_IMPORT_NOT_DEFINED]: Package import specifier "#foo" is not defined imported from ...\_.mjs
Only subpath imports (#) fail. I suspect GetPackageScopeConfig in src/node_modules.cc is missing the ToNamespacedPath call that was added to other functions in #53294 (later refactored into NormalizePath in #60425).
Additional information
No response