From cc71ee4421764adf61790986221d101604622c3a Mon Sep 17 00:00:00 2001 From: Eric Wagoner Date: Sun, 27 Sep 2026 01:21:44 -0400 Subject: [PATCH] A socket's own error closes that socket, not the server A message over the size limit or a malformed frame raised an error on the socket, which had no listener, and Node ended the process: one message from anyone could take the server down until systemd restarted it. The socket is terminated instead. Messages are capped at 1 KB, since the server never reads them. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG --- server/src/index.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/src/index.ts b/server/src/index.ts index d840cdc..463acdb 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -312,7 +312,8 @@ const server = createServer((req, res) => { }); }); -const wss = new WebSocketServer({ noServer: true }); +// The socket only ever speaks to the browser; anything the browser sends is ignored, so it may send almost nothing. +const wss = new WebSocketServer({ noServer: true, maxPayload: 1024 }); server.on('upgrade', (req, socket, head) => { const url = new URL(req.url ?? '/', 'http://localhost'); if (url.pathname !== '/ws') return socket.destroy(); @@ -332,6 +333,8 @@ server.on('upgrade', (req, socket, head) => { }; const unsubscribe = seatId === SPECTATOR ? rooms.watch(room, onChange) : rooms.subscribe(room.id, onChange); ws.on('close', unsubscribe); + // A socket's own error (a message over the limit, a malformed frame) closes that socket, never the server. + ws.on('error', () => ws.terminate()); ws.send(JSON.stringify({ type: 'hello', seat: seatId })); }); });