From 749f4963186f462d7d5b87eee2035fc1b64b6a25 Mon Sep 17 00:00:00 2001 From: Berk Date: Sat, 16 May 2026 21:20:18 +0300 Subject: [PATCH] fix: prevent sendStartGameMsg from crashing server on client disconnect (#3939) 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 If this PR fixes an issue, link it below. If not, delete these two lines. Resolves #(issue number) ## Description: Describe the PR. ## Please complete the following: - [ ] I have added screenshots for all UI updates - [ ] I process any text displayed to the user through translateText() and I've added it to the en.json file - [ ] I have added relevant tests to the test directory - [ ] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: DISCORD_USERNAME --- 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 a34448994..9cd8b6b6f 100644 --- a/src/server/GameServer.ts +++ b/src/server/GameServer.ts @@ -783,6 +783,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", @@ -793,14 +800,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), + }); } }