diff --git a/.changeset/v1-bun-remote-bindings.md b/.changeset/v1-bun-remote-bindings.md new file mode 100644 index 00000000000..72e38032d56 --- /dev/null +++ b/.changeset/v1-bun-remote-bindings.md @@ -0,0 +1,7 @@ +--- +"@cloudflare/vite-plugin": patch +--- + +Report unsupported remote bindings under Bun instead of hanging + +Starting remote bindings now fails with an actionable error explaining Bun's unsupported request routing. Use Node.js or disable remote bindings to continue local development. diff --git a/packages/remote-bindings/src/start-remote-proxy-session.test.ts b/packages/remote-bindings/src/start-remote-proxy-session.test.ts index bf954d21727..d3d0cfa247e 100644 --- a/packages/remote-bindings/src/start-remote-proxy-session.test.ts +++ b/packages/remote-bindings/src/start-remote-proxy-session.test.ts @@ -57,6 +57,30 @@ function makeErrorEvent(cause: ErrorEvent["cause"]): ErrorEvent { } describe("startRemoteProxySession error handling", () => { + it("throws a UserError under Bun before starting the session", async ({ + expect, + onTestFinished, + }) => { + const originalBunVersion = process.versions.bun; + process.versions.bun = "1.4.4"; + onTestFinished(() => { + process.versions.bun = originalBunVersion; + }); + + const thrown = await startRemoteProxySession( + {}, + { cliDisplayName: "Test CLI", logger: createTestLogger() } + ).catch((error: unknown) => error); + + expect(thrown).toBeInstanceOf(UserError); + expect(thrown).toMatchObject({ + message: expect.stringContaining( + "https://github.com/oven-sh/bun/issues/39247" + ), + telemetryMessage: "remote proxy session under bun", + }); + }); + // Regression: a `UserError` emitted asynchronously (e.g. the Miniflare // user-error case in `DevEnv.handleErrorEvent`) used to fall through to being // wrapped in a generic `Error`, which makes Wrangler treat it as an diff --git a/packages/remote-bindings/src/start-remote-proxy-session.ts b/packages/remote-bindings/src/start-remote-proxy-session.ts index e9001a7887c..08e1fb869dd 100644 --- a/packages/remote-bindings/src/start-remote-proxy-session.ts +++ b/packages/remote-bindings/src/start-remote-proxy-session.ts @@ -104,6 +104,16 @@ export async function startRemoteProxySession( } } + // The session hands its local proxy the remote connection in a control + // message sent through an undici `dispatcher`, which Bun's `fetch()` ignores, + // so every remote binding request would wait forever. + if (process.versions.bun) { + throw new UserError( + "Remote bindings can't work under Bun, because Bun's `fetch()` ignores the undici `dispatcher` that Miniflare routes them through (https://github.com/oven-sh/bun/issues/39247). Run this using Node.js, or turn remote bindings off.", + { telemetryMessage: "remote proxy session under bun" } + ); + } + options.logger.log(chalk.dim("⎔ Establishing remote connection...")); initLogger(getInternalLogger(options.logger)); const rawBindings = toRawBindings(bindings);