From b04cd3640ece0a2bab6b469c496cfb26a2de0e07 Mon Sep 17 00:00:00 2001 From: Alex K Date: Wed, 8 Jul 2026 13:47:39 -0400 Subject: [PATCH] [wrangler] Handle queue bindings in remote dev --- .changeset/silent-queues-jam.md | 7 ++++ .../startDevWorker/ConfigController.test.ts | 40 +++++++++++++++++++ .../RemoteRuntimeController.test.ts | 36 +++++++++++++++++ .../startDevWorker/RemoteRuntimeController.ts | 14 ++++++- 4 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 .changeset/silent-queues-jam.md diff --git a/.changeset/silent-queues-jam.md b/.changeset/silent-queues-jam.md new file mode 100644 index 0000000000..c87dde953c --- /dev/null +++ b/.changeset/silent-queues-jam.md @@ -0,0 +1,7 @@ +--- +"wrangler": patch +--- + +Allow `wrangler dev --remote` to start when queue producer bindings are configured + +Queue bindings are still unsupported in legacy remote dev mode, but Wrangler now omits them from remote preview uploads after warning. This lets unrelated routes keep working instead of returning 500 errors for the whole dev session. diff --git a/packages/wrangler/src/__tests__/api/startDevWorker/ConfigController.test.ts b/packages/wrangler/src/__tests__/api/startDevWorker/ConfigController.test.ts index f8d26e4a92..5c824b51ef 100644 --- a/packages/wrangler/src/__tests__/api/startDevWorker/ConfigController.test.ts +++ b/packages/wrangler/src/__tests__/api/startDevWorker/ConfigController.test.ts @@ -367,4 +367,44 @@ describe("ConfigController", () => { expect(warningCount).toBe(1); }); + + it("should warn when queues are configured in remote dev mode", async ({ + expect, + }) => { + await seed({ + "src/index.ts": dedent /* javascript */ ` + export default { + fetch() { + return new Response("hello world") + } + } + `, + "wrangler.toml": dedent /* toml */ ` + name = "my-worker" + main = "src/index.ts" + compatibility_date = "2024-06-01" + + [[queues.producers]] + binding = "QUEUE" + queue = "test-queue" + `, + }); + + const event = bus.waitFor("configUpdate"); + await controller.set({ + config: "./wrangler.toml", + dev: { + remote: true, + auth: { + accountId: "some-account-id", + apiToken: { apiToken: "some-api-token" }, + }, + }, + }); + await event; + + expect(std.warn).toContain( + "Queues are not yet supported in wrangler dev remote mode." + ); + }); }); diff --git a/packages/wrangler/src/__tests__/api/startDevWorker/RemoteRuntimeController.test.ts b/packages/wrangler/src/__tests__/api/startDevWorker/RemoteRuntimeController.test.ts index 03b1373937..12dd81af91 100644 --- a/packages/wrangler/src/__tests__/api/startDevWorker/RemoteRuntimeController.test.ts +++ b/packages/wrangler/src/__tests__/api/startDevWorker/RemoteRuntimeController.test.ts @@ -157,6 +157,42 @@ describe("RemoteRuntimeController", () => { vi.mocked(getAccessHeaders).mockResolvedValue({}); }); + describe("unsupported queue bindings", () => { + it("should omit queue producer bindings from remote preview uploads", async ({ + expect, + }) => { + const { controller, bus } = setup(); + const config = makeConfig({ + bindings: { + QUEUE: { + type: "queue", + queue_name: "test-queue", + }, + KV: { + type: "kv_namespace", + id: "test-kv-namespace", + }, + }, + }); + const bundle = makeBundle(); + + controller.onBundleStart({ type: "bundleStart", config }); + controller.onBundleComplete({ type: "bundleComplete", config, bundle }); + await bus.waitFor("reloadComplete"); + + expect(createRemoteWorkerInit).toHaveBeenCalledWith( + expect.objectContaining({ + bindings: { + KV: { + type: "kv_namespace", + id: "test-kv-namespace", + }, + }, + }) + ); + }); + }); + describe("stale bundle bail-out", () => { it("should skip stale bundles and only reload once for rapid updates", async ({ expect, diff --git a/packages/wrangler/src/api/startDevWorker/RemoteRuntimeController.ts b/packages/wrangler/src/api/startDevWorker/RemoteRuntimeController.ts index 5fae00af09..f652b2e336 100644 --- a/packages/wrangler/src/api/startDevWorker/RemoteRuntimeController.ts +++ b/packages/wrangler/src/api/startDevWorker/RemoteRuntimeController.ts @@ -35,11 +35,21 @@ import type { ReloadCompleteEvent, ReloadStartEvent, } from "./events"; -import type { Bundle, StartDevWorkerOptions, Trigger } from "./types"; +import type { Binding, Bundle, StartDevWorkerOptions, Trigger } from "./types"; import type { Route } from "@cloudflare/workers-utils"; type CreateRemoteWorkerInitProps = Parameters[0]; +function getRemotePreviewBindings( + bindings: StartDevWorkerOptions["bindings"] +): Record { + return Object.fromEntries( + Object.entries(bindings ?? {}).filter( + ([, binding]) => binding.type !== "queue" + ) + ); +} + export class RemoteRuntimeController extends RuntimeController { #abortController = new AbortController(); @@ -154,7 +164,7 @@ export class RemoteRuntimeController extends RuntimeController { assets: props.assets, legacyAssetPaths: props.legacyAssetPaths, format: props.format, - bindings: props.bindings, + bindings: getRemotePreviewBindings(props.bindings), compatibilityDate: props.compatibilityDate, compatibilityFlags: props.compatibilityFlags, });