From 5b55026ffbd116c8004680b284e48331511a4d99 Mon Sep 17 00:00:00 2001 From: Justin Persaud Date: Thu, 22 Oct 2026 12:16:20 -0400 Subject: [PATCH 1/2] Return 404 when the previous builds bucket can't be read An R2 error while looking up a file from a previous build made the Worker throw, so the request failed with an exception. It now logs the error and answers like any file no build has, so the tab gets a ChunkLoadError and recovers with a reload. --- web/cloudflare-worker/src/index.ts | 18 ++++++++++++------ web/cloudflare-worker/tests/worker.test.ts | 12 ++++++++++++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/web/cloudflare-worker/src/index.ts b/web/cloudflare-worker/src/index.ts index 605990253d84..e501b582d93b 100644 --- a/web/cloudflare-worker/src/index.ts +++ b/web/cloudflare-worker/src/index.ts @@ -71,13 +71,19 @@ async function getPreviousBuildFile(env: Env, url: URL, method: string): Promise return null; } - if (method === 'HEAD') { - const object = await env.PREVIOUS_BUILDS.head(key); - return object ? new Response(null, {headers: getPreviousBuildFileHeaders(object)}) : null; - } + try { + if (method === 'HEAD') { + const object = await env.PREVIOUS_BUILDS.head(key); + return object ? new Response(null, {headers: getPreviousBuildFileHeaders(object)}) : null; + } - const object = await env.PREVIOUS_BUILDS.get(key); - return object ? new Response(object.body, {headers: getPreviousBuildFileHeaders(object)}) : null; + const object = await env.PREVIOUS_BUILDS.get(key); + return object ? new Response(object.body, {headers: getPreviousBuildFileHeaders(object)}) : null; + } catch (error) { + // A 404 lets the tab recover with a reload, as it does for a file no build has. + console.error(`Failed to read ${key} from the previous builds bucket`, error); + return null; + } } export default { diff --git a/web/cloudflare-worker/tests/worker.test.ts b/web/cloudflare-worker/tests/worker.test.ts index 09997a2c11b4..187bbe92050e 100644 --- a/web/cloudflare-worker/tests/worker.test.ts +++ b/web/cloudflare-worker/tests/worker.test.ts @@ -260,6 +260,18 @@ describe('staging worker with files from previous builds', () => { assert.equal(await response.text(), ''); }); + test('returns 404 when the previous builds bucket fails', async () => { + // Given a chunk path whose bucket lookup fails (R2 rejects keys over 1,024 bytes) + for (const method of ['GET', 'HEAD']) { + // When it is requested + const response = await server.fetch(`/${'a'.repeat(1100)}.bundle.js`, {method}); + + // Then the Worker answers as it does for a chunk no build has, instead of throwing + assert.equal(response.status, 404, method); + assertSecurityHeaders(response); + } + }); + test('serves the current build when a previous build has the same file', async () => { // Given a file that is in both the current build and the bucket // When it is requested From e1820b8ab34d7686b25194a5607c6745ef34a973 Mon Sep 17 00:00:00 2001 From: Justin Persaud Date: Thu, 22 Oct 2026 12:16:23 -0400 Subject: [PATCH 2/2] Document the 404 when the previous builds bucket can't be read --- web/cloudflare-worker/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/cloudflare-worker/README.md b/web/cloudflare-worker/README.md index c2cd4be84b00..e4497ab23cb5 100644 --- a/web/cloudflare-worker/README.md +++ b/web/cloudflare-worker/README.md @@ -14,7 +14,7 @@ Every request runs the Worker first (`run_worker_first: true`), which reads the | HTML (`/`, `/index.html`, any SPA deep link) | Each `