diff --git a/src/bun.js/ModuleLoader.zig b/src/bun.js/ModuleLoader.zig index 9a291d5def9e..6822da57eb79 100644 --- a/src/bun.js/ModuleLoader.zig +++ b/src/bun.js/ModuleLoader.zig @@ -2554,12 +2554,18 @@ pub const RuntimeTranspilerStore = struct { } if (strings.hasPrefixComptime(import_record.path.text, "bun:")) { - import_record.path = Fs.Path.init(import_record.path.text["bun:".len..]); - import_record.path.namespace = "bun"; - import_record.is_external_without_side_effects = true; + // Validate and strip the bun: prefix for builtin modules. + // Invalid modules (e.g., "bun:invalid") are left unchanged so the + // resolver can report an error with the full "bun:invalid" name instead + // of the confusing "Cannot find package 'invalid'". + if (HardcodedModule.map.has(import_record.path.text)) { + import_record.path = Fs.Path.init(import_record.path.text["bun:".len..]); + import_record.path.namespace = "bun"; + import_record.is_external_without_side_effects = true; - if (strings.eqlComptime(import_record.path.text, "test")) { - import_record.tag = .bun_test; + if (strings.eqlComptime(import_record.path.text, "test")) { + import_record.tag = .bun_test; + } } } } diff --git a/src/bundler/bundle_v2.zig b/src/bundler/bundle_v2.zig index 0e7aa8f698ec..997d31815e9a 100644 --- a/src/bundler/bundle_v2.zig +++ b/src/bundler/bundle_v2.zig @@ -3175,17 +3175,21 @@ pub const BundleV2 = struct { } if (strings.hasPrefixComptime(import_record.path.text, "bun:")) { - import_record.path = Fs.Path.init(import_record.path.text["bun:".len..]); - import_record.path.namespace = "bun"; - import_record.source_index = Index.invalid; - import_record.is_external_without_side_effects = true; + // Validate and strip the bun: prefix for builtin modules. + // Invalid modules are left unchanged for better error messages. + if (jsc.ModuleLoader.HardcodedModule.map.has(import_record.path.text)) { + import_record.path = Fs.Path.init(import_record.path.text["bun:".len..]); + import_record.path.namespace = "bun"; + import_record.source_index = Index.invalid; + import_record.is_external_without_side_effects = true; - if (strings.eqlComptime(import_record.path.text, "test")) { - import_record.tag = .bun_test; - } + if (strings.eqlComptime(import_record.path.text, "test")) { + import_record.tag = .bun_test; + } - // don't link bun - continue; + // don't link bun + continue; + } } } diff --git a/src/linker.zig b/src/linker.zig index a71015523a8f..7693509755fc 100644 --- a/src/linker.zig +++ b/src/linker.zig @@ -176,15 +176,19 @@ pub const Linker = struct { } if (strings.hasPrefixComptime(import_record.path.text, "bun:")) { - import_record.path = Fs.Path.init(import_record.path.text["bun:".len..]); - import_record.path.namespace = "bun"; + // Validate and strip the bun: prefix for builtin modules. + // Invalid modules are left unchanged for better error messages. + if (jsc.ModuleLoader.HardcodedModule.map.has(import_record.path.text)) { + import_record.path = Fs.Path.init(import_record.path.text["bun:".len..]); + import_record.path.namespace = "bun"; - if (strings.eqlComptime(import_record.path.text, "test")) { - import_record.tag = .bun_test; - } + if (strings.eqlComptime(import_record.path.text, "test")) { + import_record.tag = .bun_test; + } - // don't link bun - continue; + // don't link bun + continue; + } } // Resolve dynamic imports lazily for perf diff --git a/test/regression/issue/invalid-bun-module-prefix.test.ts b/test/regression/issue/invalid-bun-module-prefix.test.ts new file mode 100644 index 000000000000..4aa49ad7e18b --- /dev/null +++ b/test/regression/issue/invalid-bun-module-prefix.test.ts @@ -0,0 +1,22 @@ +import { expect, test } from "bun:test"; +import { bunEnv, bunExe, tempDirWithFiles } from "harness"; + +test("invalid bun: module should preserve prefix in error", async () => { + const dir = tempDirWithFiles("bun-invalid-module", { + "test.js": 'import foo from "bun:apskdaposkdpok"', + }); + + const { stderr } = Bun.spawnSync({ + cmd: [bunExe(), "test.js"], + cwd: dir, + env: bunEnv, + stderr: "pipe", + }); + + const output = stderr.toString(); + // Error should mention "bun:apskdaposkdpok" not just "apskdaposkdpok" + expect(output).toContain("bun:apskdaposkdpok"); + // The error could be "Cannot find package" or "Cannot resolve invalid URL" + // The key is that it shows the full "bun:..." prefix + expect(output).toMatch(/Cannot (find package|resolve invalid URL)/); +});