From 05178f376e298188b2628f5b3a78d7249717bc39 Mon Sep 17 00:00:00 2001 From: LeSingh1 Date: Mon, 3 Aug 2026 20:08:36 -0700 Subject: [PATCH 1/2] fix(workers-utils): stop iterating a non-array queues.consumers value `validateQueues` recorded the `should be an array` diagnostic for a non-array `queues.consumers` but then fell through to the `for` loop instead of stopping, so the diagnostic it had just prepared never reached the user. `"consumers": null` threw `TypeError: Cannot read properties of null (reading 'length')` out of config validation, and `"consumers": "my-queue"` iterated the string's characters, emitting one spurious `"queues.consumers[N]" should be a objects` error per character. Guard the loop behind the array check, matching `queues.producers`, which returns early via `validateBindingArray`. --- .changeset/queues-consumers-not-array.md | 9 ++++++ .../workers-utils/src/config/validation.ts | 14 +++++----- .../normalize-and-validate-config.test.ts | 28 +++++++++++++++++++ 3 files changed, 44 insertions(+), 7 deletions(-) create mode 100644 .changeset/queues-consumers-not-array.md diff --git a/.changeset/queues-consumers-not-array.md b/.changeset/queues-consumers-not-array.md new file mode 100644 index 00000000000..9c78dc9e164 --- /dev/null +++ b/.changeset/queues-consumers-not-array.md @@ -0,0 +1,9 @@ +--- +"@cloudflare/workers-utils": patch +--- + +Report a non-array `queues.consumers` as a configuration error instead of crashing + +`validateQueues` pushed the `The field "queues.consumers" should be an array` diagnostic and then iterated the value anyway. `"queues": { "consumers": null }` therefore threw `TypeError: Cannot read properties of null (reading 'length')` before the diagnostic could be rendered, and `"queues": { "consumers": "my-queue" }` walked the string character by character, adding one bogus `"queues.consumers[0]" should be a objects, but got "m"` error per character on top of the real one. + +The intended error is now the only thing reported, matching how the sibling `queues.producers` field already behaves. diff --git a/packages/workers-utils/src/config/validation.ts b/packages/workers-utils/src/config/validation.ts index 0f17322d254..4ce1e8263d6 100644 --- a/packages/workers-utils/src/config/validation.ts +++ b/packages/workers-utils/src/config/validation.ts @@ -5114,13 +5114,13 @@ function validateQueues(envName: string): ValidatorFn { )}.` ); isValid = false; - } - - for (let i = 0; i < consumers.length; i++) { - const consumer = consumers[i]; - const consumerPath = `${fieldPath}.consumers[${i}]`; - if (!validateConsumer(diagnostics, consumerPath, consumer, config)) { - isValid = false; + } else { + for (let i = 0; i < consumers.length; i++) { + const consumer = consumers[i]; + const consumerPath = `${fieldPath}.consumers[${i}]`; + if (!validateConsumer(diagnostics, consumerPath, consumer, config)) { + isValid = false; + } } } } diff --git a/packages/workers-utils/tests/config/validation/normalize-and-validate-config.test.ts b/packages/workers-utils/tests/config/validation/normalize-and-validate-config.test.ts index fdc773a571a..9ff10b10f9f 100644 --- a/packages/workers-utils/tests/config/validation/normalize-and-validate-config.test.ts +++ b/packages/workers-utils/tests/config/validation/normalize-and-validate-config.test.ts @@ -4758,6 +4758,34 @@ describe("normalizeAndValidateConfig()", () => { `); }); + it("should error if queues.consumers is null", ({ expect }) => { + const { diagnostics } = normalizeAndValidateConfig( + { queues: { consumers: null } } as unknown as RawConfig, + undefined, + undefined, + { env: undefined } + ); + + expect(diagnostics.renderErrors()).toMatchInlineSnapshot(` + "Processing wrangler configuration: + - The field "queues.consumers" should be an array but got null." + `); + }); + + it("should error once if queues.consumers is a string", ({ expect }) => { + const { diagnostics } = normalizeAndValidateConfig( + { queues: { consumers: "my-queue" } } as unknown as RawConfig, + undefined, + undefined, + { env: undefined } + ); + + expect(diagnostics.renderErrors()).toMatchInlineSnapshot(` + "Processing wrangler configuration: + - The field "queues.consumers" should be an array but got "my-queue"." + `); + }); + it("should error if queues producer bindings are not valid", ({ expect, }) => { From 48f01376a5500274b2b5f1de07127f27d9d1c557 Mon Sep 17 00:00:00 2001 From: Dario Piotrowicz Date: Fri, 7 Aug 2026 11:21:55 +0100 Subject: [PATCH 2/2] Update .changeset/queues-consumers-not-array.md Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .changeset/queues-consumers-not-array.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.changeset/queues-consumers-not-array.md b/.changeset/queues-consumers-not-array.md index 9c78dc9e164..35ba9a67268 100644 --- a/.changeset/queues-consumers-not-array.md +++ b/.changeset/queues-consumers-not-array.md @@ -2,8 +2,6 @@ "@cloudflare/workers-utils": patch --- -Report a non-array `queues.consumers` as a configuration error instead of crashing +Report an invalid `queues.consumers` value as a configuration error instead of crashing -`validateQueues` pushed the `The field "queues.consumers" should be an array` diagnostic and then iterated the value anyway. `"queues": { "consumers": null }` therefore threw `TypeError: Cannot read properties of null (reading 'length')` before the diagnostic could be rendered, and `"queues": { "consumers": "my-queue" }` walked the string character by character, adding one bogus `"queues.consumers[0]" should be a objects, but got "m"` error per character on top of the real one. - -The intended error is now the only thing reported, matching how the sibling `queues.producers` field already behaves. +Previously, setting `queues.consumers` to something other than an array (for example `null` or a string) could crash Wrangler or produce a flood of confusing extra errors. You now get a single clear message telling you the field must be an array.