From aa6f844f007e6ca733532bbfe2b6007e95c1444e Mon Sep 17 00:00:00 2001 From: 22314621 Date: Sat, 16 May 2026 16:07:38 +0300 Subject: [PATCH] fix: prevent sendStartGameMsg from crashing server on client disconnect The catch block in sendStartGameMsg() re-throws the error, which means a single client's WebSocket failure (e.g. disconnected during game start) propagates up and can crash the entire game server. The start() method calls sendStartGameMsg() in a forEach loop over all clients, so one bad client kills the game for everyone. Changes: - Added readyState check before sending - Replaced re-throw with structured error logging - A single client failure now logs the error and continues gracefully --- src/server/GameServer.ts | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/server/GameServer.ts b/src/server/GameServer.ts index 43f26ce388..d165842a4e 100644 --- a/src/server/GameServer.ts +++ b/src/server/GameServer.ts @@ -781,6 +781,13 @@ export class GameServer { }); try { + if (ws.readyState !== WebSocket.OPEN) { + this.log.warn(`WebSocket not open, skipping start message`, { + clientID: client.clientID, + readyState: ws.readyState, + }); + return; + } ws.send( JSON.stringify({ type: "start", @@ -791,14 +798,10 @@ export class GameServer { } satisfies ServerStartGameMessage), ); } catch (error) { - // can be enabled once we can use {cause: error} in Error constructor starting with ES2022 - // eslint-disable-next-line preserve-caught-error - throw new Error( - `error sending start message for game ${this.id}, ${error}`.substring( - 0, - 250, - ), - ); + this.log.error(`error sending start message for game ${this.id}`, { + clientID: client.clientID, + error: error instanceof Error ? error.message : String(error), + }); } }