{"record":{"id":"a8ab947d800bb886","repo":"ppy/osu","slug":"connection-closed-by-remote-host","errorCode":null,"errorMessage":"Connection closed by remote host.","messagePattern":"Connection closed by remote host\\.","errorType":"exception","errorClass":"WebException","httpStatus":null,"severity":"warning","filePath":"osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClient.cs","lineNumber":77,"sourceCode":"\r\n                                Debug.Assert(message != null);\r\n\r\n                                if (message.Error != null)\r\n                                {\r\n                                    Logger.Log($\"{GetType().ReadableName()} error: {message.Error}\", LoggingTarget.Network);\r\n                                    break;\r\n                                }\r\n\r\n                                MessageReceived?.Invoke(message);\r\n                            }\r\n\r\n                            break;\r\n\r\n                        case WebSocketMessageType.Binary:\r\n                            throw new NotImplementedException(\"Binary message type not supported.\");\r\n\r\n                        case WebSocketMessageType.Close:\r\n                            throw new WebException(\"Connection closed by remote host.\");\r\n                    }\r\n                }\r\n                catch (Exception ex)\r\n                {\r\n                    await InvokeClosed(ex).ConfigureAwait(false);\r\n                    return;\r\n                }\r\n            }\r\n        }, cancellationToken);\r\n\r\n        private async Task closeAsync()\r\n        {\r\n            try\r\n            {\r\n                await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, @\"Disconnecting\", CancellationToken.None).ConfigureAwait(false);\r\n            }\r\n            catch\r\n            {\r","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/ppy/osu/blob/d9c73e12adff2feaae4a3e158d36fe5883faf6ca/osu.Game/Online/Notifications/WebSocket/WebSocketNotificationsClient.cs#L59-L95","documentation":"Thrown as WebException by WebSocketNotificationsClient when it receives a Close frame from the remote host. It is the channel for normal and abnormal connection termination, surfaced through InvokeClosed so the connector can reconnect.","triggerScenarios":"The notifications server sends WebSocketMessageType.Close (clean shutdown), or any code path reaching the Close branch. The exception is caught immediately and passed to InvokeClosed.","commonSituations":"Server restart/deploy, idle timeout, load-balancer dropping the socket, or the user being logged out. Not necessarily a defect; it is the reconnect signal.","solutions":["Treat this as a transient disconnect: let PersistentEndpointClientConnector handle reconnect with backoff.","Verify authentication/session is still valid before reconnect (an expired session causes immediate re-close loops).","Check server status and network if reconnects cycle rapidly."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// close frames cannot be pre-validated; the strategy is reconnect-with-backoff on the Closed event.","typeGuard":null,"tryCatchPattern":"// InvokeClosed(ex) is already called; subscribe to connector Closed/IsConnected\n// and trigger a reconnect with exponential backoff.","preventionTips":["Validate the session token before reconnect to avoid close loops.","Use the PersistentEndpointClientConnector's built-in reconnect/backoff.","Monitor rapid close cycles as a signal of auth or server problems."],"tags":["websocket","notifications","network","reconnect","web-exception"],"backgroundTag":null,"analyzedSha":"d9c73e12adff2feaae4a3e158d36fe5883faf6ca","analyzedAt":"2026-08-13T14:12:54.015Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}