From 855cf2a9ebf921bb04104b580279de67a2b01325 Mon Sep 17 00:00:00 2001 From: Sertug17 Date: Wed, 5 Aug 2026 09:55:45 +0300 Subject: [PATCH 1/5] [wrangler] Fix modules-watch-stub injection when bundle:false (fixes #14845) --- .changeset/fix-modules-watch-stub-no-bundle.md | 11 +++++++++++ packages/wrangler/src/deployment-bundle/bundle.ts | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 .changeset/fix-modules-watch-stub-no-bundle.md diff --git a/.changeset/fix-modules-watch-stub-no-bundle.md b/.changeset/fix-modules-watch-stub-no-bundle.md new file mode 100644 index 00000000000..68b8cf639ed --- /dev/null +++ b/.changeset/fix-modules-watch-stub-no-bundle.md @@ -0,0 +1,11 @@ +--- +"wrangler": patch +--- + +[wrangler] Fix `No such module "wrangler:modules-watch"` crash when running `wrangler pages dev` with `no_bundle = true` + +When `bundle: false` (e.g. `no_bundle = true` in `wrangler.toml`, or `--no-bundle` flag), esbuild does not resolve imports inside injected files. Previously, `modules-watch-stub.js` was always injected whenever `watch: true`, regardless of the `bundle` option. This left `import "wrangler:modules-watch"` as an unresolved import in the output, causing a runtime crash in workerd: `Uncaught Error: No such module "wrangler:modules-watch"`. + +The fix is to only inject `modules-watch-stub.js` when `bundle: true`. When `bundle: false`, file-system watching is already handled via chokidar, so the esbuild-internal watch stub is not needed. + +Fixes #14845. diff --git a/packages/wrangler/src/deployment-bundle/bundle.ts b/packages/wrangler/src/deployment-bundle/bundle.ts index ee99209fa73..b2a2f62b3df 100644 --- a/packages/wrangler/src/deployment-bundle/bundle.ts +++ b/packages/wrangler/src/deployment-bundle/bundle.ts @@ -317,7 +317,7 @@ export async function bundleWorker( inject.push(...(result.inject ?? [])); } - if (watch) { + if (watch && bundle) { // `esbuild` doesn't support returning `watch*` options from `onStart()` // plugin callbacks. Instead, we define an empty virtual module that is // imported in this injected module. Importing that module registers watchers. @@ -446,7 +446,7 @@ export async function bundleWorker( // alive and preventing clean exit. let ctx: esbuild.BuildContext | undefined; try { - if (watch) { + if (watch && bundle) { ctx = await esbuild.context(buildOptions); await ctx.watch(); result = await initialBuildResultPromise; From e7f52c8b0c97b90dc2eac63fc0c9685f83e87cb0 Mon Sep 17 00:00:00 2001 From: Sertug17 Date: Wed, 5 Aug 2026 10:02:15 +0300 Subject: [PATCH 2/5] Revert esbuild context watch condition (only stub injection needed the bundle guard) --- packages/wrangler/src/deployment-bundle/bundle.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/wrangler/src/deployment-bundle/bundle.ts b/packages/wrangler/src/deployment-bundle/bundle.ts index b2a2f62b3df..bdbbfce05c0 100644 --- a/packages/wrangler/src/deployment-bundle/bundle.ts +++ b/packages/wrangler/src/deployment-bundle/bundle.ts @@ -446,7 +446,7 @@ export async function bundleWorker( // alive and preventing clean exit. let ctx: esbuild.BuildContext | undefined; try { - if (watch && bundle) { + if (watch) { ctx = await esbuild.context(buildOptions); await ctx.watch(); result = await initialBuildResultPromise; From 3137ea01943c8b7a46c25ae408c854eba6b9f233 Mon Sep 17 00:00:00 2001 From: Sertug17 Date: Wed, 5 Aug 2026 10:03:24 +0300 Subject: [PATCH 3/5] Fix changeset: use wrangler.json config format --- .changeset/fix-modules-watch-stub-no-bundle.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/fix-modules-watch-stub-no-bundle.md b/.changeset/fix-modules-watch-stub-no-bundle.md index 68b8cf639ed..690ae6064f8 100644 --- a/.changeset/fix-modules-watch-stub-no-bundle.md +++ b/.changeset/fix-modules-watch-stub-no-bundle.md @@ -4,7 +4,7 @@ [wrangler] Fix `No such module "wrangler:modules-watch"` crash when running `wrangler pages dev` with `no_bundle = true` -When `bundle: false` (e.g. `no_bundle = true` in `wrangler.toml`, or `--no-bundle` flag), esbuild does not resolve imports inside injected files. Previously, `modules-watch-stub.js` was always injected whenever `watch: true`, regardless of the `bundle` option. This left `import "wrangler:modules-watch"` as an unresolved import in the output, causing a runtime crash in workerd: `Uncaught Error: No such module "wrangler:modules-watch"`. +When `bundle: false` (e.g. `"no_bundle": true` in `wrangler.json`, or `--no-bundle` flag), esbuild does not resolve imports inside injected files. Previously, `modules-watch-stub.js` was always injected whenever `watch: true`, regardless of the `bundle` option. This left `import "wrangler:modules-watch"` as an unresolved import in the output, causing a runtime crash in workerd: `Uncaught Error: No such module "wrangler:modules-watch"`. The fix is to only inject `modules-watch-stub.js` when `bundle: true`. When `bundle: false`, file-system watching is already handled via chokidar, so the esbuild-internal watch stub is not needed. From f26dd6d16410c0629a5cae81431c41a164b2b087 Mon Sep 17 00:00:00 2001 From: Sertug17 Date: Wed, 5 Aug 2026 10:39:13 +0300 Subject: [PATCH 4/5] Fix changeset: user-facing language --- .changeset/fix-modules-watch-stub-no-bundle.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.changeset/fix-modules-watch-stub-no-bundle.md b/.changeset/fix-modules-watch-stub-no-bundle.md index 690ae6064f8..3b58b31d8f7 100644 --- a/.changeset/fix-modules-watch-stub-no-bundle.md +++ b/.changeset/fix-modules-watch-stub-no-bundle.md @@ -4,8 +4,4 @@ [wrangler] Fix `No such module "wrangler:modules-watch"` crash when running `wrangler pages dev` with `no_bundle = true` -When `bundle: false` (e.g. `"no_bundle": true` in `wrangler.json`, or `--no-bundle` flag), esbuild does not resolve imports inside injected files. Previously, `modules-watch-stub.js` was always injected whenever `watch: true`, regardless of the `bundle` option. This left `import "wrangler:modules-watch"` as an unresolved import in the output, causing a runtime crash in workerd: `Uncaught Error: No such module "wrangler:modules-watch"`. - -The fix is to only inject `modules-watch-stub.js` when `bundle: true`. When `bundle: false`, file-system watching is already handled via chokidar, so the esbuild-internal watch stub is not needed. - -Fixes #14845. +Running `wrangler dev` or `wrangler pages dev` with bundling disabled (`"no_bundle": true` in `wrangler.json`, or the `--no-bundle` flag) no longer crashes at startup with `Uncaught Error: No such module "wrangler:modules-watch"`. Live reloading on file changes continues to work as before. From 1af6db6b5b3d04819febb4597a66ffb5813fa806 Mon Sep 17 00:00:00 2001 From: Edmund Hung Date: Thu, 6 Aug 2026 14:58:45 +0100 Subject: [PATCH 5/5] test(wrangler): cover no-bundle watch stub --- .../fix-modules-watch-stub-no-bundle.md | 2 +- .../startDevWorker/BundleController.test.ts | 24 +++++++++++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/.changeset/fix-modules-watch-stub-no-bundle.md b/.changeset/fix-modules-watch-stub-no-bundle.md index 3b58b31d8f7..267787242d4 100644 --- a/.changeset/fix-modules-watch-stub-no-bundle.md +++ b/.changeset/fix-modules-watch-stub-no-bundle.md @@ -2,6 +2,6 @@ "wrangler": patch --- -[wrangler] Fix `No such module "wrangler:modules-watch"` crash when running `wrangler pages dev` with `no_bundle = true` +Fix `wrangler dev` commands crashing with `No such module "wrangler:modules-watch"` when `"no_bundle": true` Running `wrangler dev` or `wrangler pages dev` with bundling disabled (`"no_bundle": true` in `wrangler.json`, or the `--no-bundle` flag) no longer crashes at startup with `Uncaught Error: No such module "wrangler:modules-watch"`. Live reloading on file changes continues to work as before. diff --git a/packages/wrangler/src/__tests__/api/startDevWorker/BundleController.test.ts b/packages/wrangler/src/__tests__/api/startDevWorker/BundleController.test.ts index 695194008b0..95d37bd9b59 100644 --- a/packages/wrangler/src/__tests__/api/startDevWorker/BundleController.test.ts +++ b/packages/wrangler/src/__tests__/api/startDevWorker/BundleController.test.ts @@ -87,7 +87,13 @@ describe("BundleController", { retry: 5, timeout: 10_000 }, () => { afterEach(() => controller.teardown()); describe("happy path bundle + watch", () => { - test("single ts source file", async ({ expect }) => { + test.for([ + { name: "bundled", build: {} }, + { + name: "unbundled with entrypoint processing", + build: { bundle: false, processEntrypoint: true }, + }, + ])("single ts source file ($name)", async ({ build }, { expect }) => { await seed({ "src/index.ts": dedent /* javascript */ ` export default { @@ -101,11 +107,17 @@ describe("BundleController", { retry: 5, timeout: 10_000 }, () => { const config = configDefaults({ entrypoint: path.resolve("src/index.ts"), projectRoot: path.resolve("src"), + build, }); const ev = bus.waitFor("bundleComplete"); controller.onConfigUpdate({ type: "configUpdate", config }); - expect(findSourceFile((await ev).bundle.entrypointSource, "index.ts")) - .toMatchInlineSnapshot(` + const initialSource = (await ev).bundle.entrypointSource; + expect(initialSource).not.toContain("wrangler:modules-watch"); + if (build.bundle === false) { + return; + } + expect(initialSource).toContain("hello world"); + expect(findSourceFile(initialSource, "index.ts")).toMatchInlineSnapshot(` "// index.ts var index_exports = {}; __export(index_exports, { @@ -131,8 +143,10 @@ describe("BundleController", { retry: 5, timeout: 10_000 }, () => { } satisfies ExportedHandler `, }); - expect(findSourceFile((await ev2).bundle.entrypointSource, "index.ts")) - .toMatchInlineSnapshot(` + const updatedSource = (await ev2).bundle.entrypointSource; + expect(updatedSource).not.toContain("wrangler:modules-watch"); + expect(updatedSource).toContain("hello world 2"); + expect(findSourceFile(updatedSource, "index.ts")).toMatchInlineSnapshot(` "// index.ts var index_exports = {}; __export(index_exports, {