From cdd8e5131a69e27ee87e76e56cdb43469f7208a1 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Mon, 23 Mar 2026 12:26:22 +0000 Subject: [PATCH] fix(miniflare): disable undici Pool headersTimeout and bodyTimeout for local dev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Miniflare's undici Pool instances were inheriting the default 300s (5 minute) headersTimeout and bodyTimeout. Requests taking longer than that — streaming responses, large uploads, long-polling, or compute-heavy Workers — would be killed with a 'request failed' error. Setting both to 0 disables them entirely, consistent with the existing pattern in dev-registry.worker.ts where Node.js HTTP server timeouts are also disabled for the same reason. Fixes #12949 --- .changeset/miniflare-disable-pool-timeouts.md | 9 +++++++++ packages/miniflare/src/index.ts | 4 ++++ packages/miniflare/src/plugins/core/proxy/fetch-sync.ts | 4 ++++ 3 files changed, 17 insertions(+) create mode 100644 .changeset/miniflare-disable-pool-timeouts.md diff --git a/.changeset/miniflare-disable-pool-timeouts.md b/.changeset/miniflare-disable-pool-timeouts.md new file mode 100644 index 0000000000..0392a693cd --- /dev/null +++ b/.changeset/miniflare-disable-pool-timeouts.md @@ -0,0 +1,9 @@ +--- +"miniflare": patch +--- + +fix: disable undici Pool request timeouts for local dev + +Miniflare's undici `Pool` instances were using the default `headersTimeout` and `bodyTimeout` of 300 seconds (5 minutes). Any request taking longer than that — streaming responses, large uploads, long-polling, or compute-heavy Workers — would be silently killed with a "request failed" error. + +Setting both timeouts to `0` disables them entirely, which is the correct behaviour for a local development tool where there is no reason to enforce request timeouts. diff --git a/packages/miniflare/src/index.ts b/packages/miniflare/src/index.ts index fdca76a68f..e6570c318a 100644 --- a/packages/miniflare/src/index.ts +++ b/packages/miniflare/src/index.ts @@ -2143,6 +2143,10 @@ export class Miniflare { if (previousEntryURL?.toString() !== this.#runtimeEntryURL.toString()) { this.#runtimeDispatcher = new Pool(this.#runtimeEntryURL, { connect: { rejectUnauthorized: false }, + // Disable timeouts for local dev — long-running responses (streaming, + // slow uploads, long-polling) should not be killed by undici defaults. + headersTimeout: 0, + bodyTimeout: 0, }); } if (this.#proxyClient === undefined) { diff --git a/packages/miniflare/src/plugins/core/proxy/fetch-sync.ts b/packages/miniflare/src/plugins/core/proxy/fetch-sync.ts index c9940cbb86..fc9c7122df 100644 --- a/packages/miniflare/src/plugins/core/proxy/fetch-sync.ts +++ b/packages/miniflare/src/plugins/core/proxy/fetch-sync.ts @@ -54,6 +54,10 @@ port.addEventListener("message", async (event) => { dispatcherUrl = url; dispatcher = new Pool(url, { connect: { rejectUnauthorized: false }, + // Disable timeouts for local dev — long-running responses (streaming, + // slow uploads, long-polling) should not be killed by undici defaults. + headersTimeout: 0, + bodyTimeout: 0, }); } headers["${CoreHeaders.OP_SYNC}"] = "true";