From d7cac25b24e447796cf4b61156a160cc04a0cf6f Mon Sep 17 00:00:00 2001 From: Travis Bonnet Date: Sat, 4 Apr 2026 21:34:19 -0500 Subject: [PATCH 1/2] fix(cloudflare): exclude queue consumers from prerender worker config The prerender worker's config callback was spreading the entire entryWorkerConfig, including queues.consumers. When Miniflare sees two workers both registered as consumers of the same queue, it rejects with ERR_MULTIPLE_CONSUMERS. The prerender worker only renders static HTML and has no need for queue consumer registrations. This fix destructures queues from the entry worker config and only preserves queue producers (bindings) in the prerender worker config. Closes #16199 Co-Authored-By: Tadao --- .../fix-cf-prerender-queue-consumers.md | 5 +++ packages/integrations/cloudflare/src/index.ts | 8 +++-- .../astro.config.mjs | 7 ++++ .../prerender-queue-consumers/package.json | 9 +++++ .../src/pages/api.ts | 9 +++++ .../src/pages/index.astro | 10 ++++++ .../prerender-queue-consumers/wrangler.jsonc | 18 ++++++++++ .../test/prerender-queue-consumers.test.js | 33 +++++++++++++++++++ 8 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 .changeset/fix-cf-prerender-queue-consumers.md create mode 100644 packages/integrations/cloudflare/test/fixtures/prerender-queue-consumers/astro.config.mjs create mode 100644 packages/integrations/cloudflare/test/fixtures/prerender-queue-consumers/package.json create mode 100644 packages/integrations/cloudflare/test/fixtures/prerender-queue-consumers/src/pages/api.ts create mode 100644 packages/integrations/cloudflare/test/fixtures/prerender-queue-consumers/src/pages/index.astro create mode 100644 packages/integrations/cloudflare/test/fixtures/prerender-queue-consumers/wrangler.jsonc create mode 100644 packages/integrations/cloudflare/test/prerender-queue-consumers.test.js diff --git a/.changeset/fix-cf-prerender-queue-consumers.md b/.changeset/fix-cf-prerender-queue-consumers.md new file mode 100644 index 000000000000..99a09a150702 --- /dev/null +++ b/.changeset/fix-cf-prerender-queue-consumers.md @@ -0,0 +1,5 @@ +--- +'@astrojs/cloudflare': patch +--- + +Fixes `ERR_MULTIPLE_CONSUMERS` error when using Cloudflare Queues with prerendered pages. The prerender worker config callback now excludes `queues.consumers` from the entry worker config, since the prerender worker only renders static HTML and should not register as a queue consumer. Queue producers (bindings) are preserved. diff --git a/packages/integrations/cloudflare/src/index.ts b/packages/integrations/cloudflare/src/index.ts index 5e7c4481f619..5230da05d624 100644 --- a/packages/integrations/cloudflare/src/index.ts +++ b/packages/integrations/cloudflare/src/index.ts @@ -181,11 +181,15 @@ export default function createIntegration({ experimental: { prerenderWorker: { config(_, { entryWorkerConfig }) { + const { queues, ...restWorkerConfig } = entryWorkerConfig; return { - ...entryWorkerConfig, + ...restWorkerConfig, name: 'prerender', + ...(queues?.producers?.length && { + queues: { producers: queues.producers }, + }), ...(needsImagesBinding && - !entryWorkerConfig.images && { + !restWorkerConfig.images && { images: { binding: imagesBindingName }, }), }; diff --git a/packages/integrations/cloudflare/test/fixtures/prerender-queue-consumers/astro.config.mjs b/packages/integrations/cloudflare/test/fixtures/prerender-queue-consumers/astro.config.mjs new file mode 100644 index 000000000000..339f0e2a49c0 --- /dev/null +++ b/packages/integrations/cloudflare/test/fixtures/prerender-queue-consumers/astro.config.mjs @@ -0,0 +1,7 @@ +import cloudflare from '@astrojs/cloudflare'; +import { defineConfig } from 'astro/config'; + +export default defineConfig({ + adapter: cloudflare(), + output: 'server', +}); diff --git a/packages/integrations/cloudflare/test/fixtures/prerender-queue-consumers/package.json b/packages/integrations/cloudflare/test/fixtures/prerender-queue-consumers/package.json new file mode 100644 index 000000000000..5e57f22f1754 --- /dev/null +++ b/packages/integrations/cloudflare/test/fixtures/prerender-queue-consumers/package.json @@ -0,0 +1,9 @@ +{ + "name": "@test/astro-cloudflare-prerender-queue-consumers", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/cloudflare": "workspace:*", + "astro": "workspace:*" + } +} diff --git a/packages/integrations/cloudflare/test/fixtures/prerender-queue-consumers/src/pages/api.ts b/packages/integrations/cloudflare/test/fixtures/prerender-queue-consumers/src/pages/api.ts new file mode 100644 index 000000000000..3060e9427491 --- /dev/null +++ b/packages/integrations/cloudflare/test/fixtures/prerender-queue-consumers/src/pages/api.ts @@ -0,0 +1,9 @@ +import type { APIRoute } from 'astro'; + +export const prerender = false; + +export const GET: APIRoute = async () => { + return new Response(JSON.stringify({ ok: true }), { + headers: { 'Content-Type': 'application/json' }, + }); +}; diff --git a/packages/integrations/cloudflare/test/fixtures/prerender-queue-consumers/src/pages/index.astro b/packages/integrations/cloudflare/test/fixtures/prerender-queue-consumers/src/pages/index.astro new file mode 100644 index 000000000000..55e12f5dd94a --- /dev/null +++ b/packages/integrations/cloudflare/test/fixtures/prerender-queue-consumers/src/pages/index.astro @@ -0,0 +1,10 @@ +--- +// This page is prerendered by default (output: 'server' with no opt-out) +// Actually, in output: 'server' mode, pages are server-rendered by default. +// We explicitly mark this as prerendered. +export const prerender = true; +--- + +Prerendered +

Prerendered Page

+ diff --git a/packages/integrations/cloudflare/test/fixtures/prerender-queue-consumers/wrangler.jsonc b/packages/integrations/cloudflare/test/fixtures/prerender-queue-consumers/wrangler.jsonc new file mode 100644 index 000000000000..6ec9e7179b12 --- /dev/null +++ b/packages/integrations/cloudflare/test/fixtures/prerender-queue-consumers/wrangler.jsonc @@ -0,0 +1,18 @@ +{ + "name": "prerender-queue-consumers", + "main": "@astrojs/cloudflare/entrypoints/server", + "compatibility_date": "2026-01-28", + "queues": { + "consumers": [ + { + "queue": "my-queue" + } + ], + "producers": [ + { + "binding": "MY_QUEUE", + "queue": "my-queue" + } + ] + } +} diff --git a/packages/integrations/cloudflare/test/prerender-queue-consumers.test.js b/packages/integrations/cloudflare/test/prerender-queue-consumers.test.js new file mode 100644 index 000000000000..c44729c698e9 --- /dev/null +++ b/packages/integrations/cloudflare/test/prerender-queue-consumers.test.js @@ -0,0 +1,33 @@ +import * as assert from 'node:assert/strict'; +import { after, before, describe, it } from 'node:test'; +import { loadFixture } from './_test-utils.js'; + +describe('Prerender with queue consumers', () => { + let fixture; + let previewServer; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/prerender-queue-consumers/', + }); + await fixture.build(); + previewServer = await fixture.preview(); + }); + + after(async () => { + previewServer.stop(); + }); + + it('builds and previews without ERR_MULTIPLE_CONSUMERS', async () => { + // The prerendered page should be accessible + const res = await fixture.fetch('/'); + const html = await res.text(); + assert.ok(html.includes('Prerendered Page')); + }); + + it('serves the SSR endpoint', async () => { + const res = await fixture.fetch('/api'); + const json = await res.json(); + assert.deepEqual(json, { ok: true }); + }); +}); From cb44e40a467ad44ec89683774465ab059401d6ac Mon Sep 17 00:00:00 2001 From: Travis Bonnet Date: Tue, 7 Apr 2026 00:38:51 -0500 Subject: [PATCH 2/2] chore: update pnpm lockfile Co-Authored-By: Claude Opus 4.6 (1M context) --- pnpm-lock.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 51689c6b75e8..a8f1694837cc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4976,6 +4976,15 @@ importers: specifier: workspace:* version: link:../../../../../astro + packages/integrations/cloudflare/test/fixtures/prerender-queue-consumers: + dependencies: + '@astrojs/cloudflare': + specifier: workspace:* + version: link:../../.. + astro: + specifier: workspace:* + version: link:../../../../../astro + packages/integrations/cloudflare/test/fixtures/prerender-styles: dependencies: '@astrojs/cloudflare':