From 9dc45f751aafabd0fc4237983d5f66fd9faa8c8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kr=C3=BCger?= Date: Sat, 15 Aug 2026 19:46:41 +0200 Subject: [PATCH] Delegate non-/ws/runs upgrade requests to Next instead of dropping them Our upgrade handler on the shared httpServer was destroying every socket that wasn't for /ws/runs, which silently killed Next's own dev-mode HMR websocket (/_next/hmr) too - breaking hot reload with no useful error, just a failed WebSocket connection in the browser console. Delegate to app.getUpgradeHandler() instead, which must be called after prepare(). Co-Authored-By: Claude Sonnet 5 --- app/server.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/server.ts b/app/server.ts index de270ee..f7714e8 100644 --- a/app/server.ts +++ b/app/server.ts @@ -23,6 +23,8 @@ const app = next({ dev, hostname, port }); const handle = app.getRequestHandler(); app.prepare().then(() => { + const nextUpgradeHandler = app.getUpgradeHandler(); + const httpServer = createServer((req, res) => { handle(req, res); }); @@ -33,7 +35,8 @@ app.prepare().then(() => { httpServer.on("upgrade", (req, socket, head) => { const { pathname } = new URL(req.url ?? "/", "http://internal"); if (pathname !== "/ws/runs") { - socket.destroy(); + // Anything else (e.g. Next's own dev-mode HMR websocket at /_next/hmr) is Next's to handle. + nextUpgradeHandler(req, socket, head).catch(() => socket.destroy()); return; }