{"record":{"id":"5a4ce968b16adf5a","repo":"ppy/osu","slug":"cannot-create-a-multiplayer-room-while-already-in","errorCode":null,"errorMessage":"Cannot create a multiplayer room while already in one.","messagePattern":"Cannot create a multiplayer room while already in one\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"osu.Game/Online/Multiplayer/MultiplayerClient.cs","lineNumber":240,"sourceCode":"                        LeaveRoom().FireAndForget();\r\n\r\n                    MatchmakingQueueLeft?.Invoke();\r\n                }\r\n            }));\r\n        }\r\n\r\n        private readonly TaskChain joinOrLeaveTaskChain = new TaskChain();\r\n        private CancellationTokenSource? joinCancellationSource;\r\n\r\n        /// <summary>\r\n        /// Creates and joins a <see cref=\"MultiplayerRoom\"/> described by an API <see cref=\"Room\"/>.\r\n        /// </summary>\r\n        /// <param name=\"room\">The API <see cref=\"Room\"/> describing the room to create.</param>\r\n        /// <exception cref=\"InvalidOperationException\">If the current user is already in another room.</exception>\r\n        public async Task CreateRoom(Room room)\r\n        {\r\n            if (Room != null)\r\n                throw new InvalidOperationException(\"Cannot create a multiplayer room while already in one.\");\r\n\r\n            var cancellationSource = joinCancellationSource = new CancellationTokenSource();\r\n\r\n            await joinOrLeaveTaskChain.Add(async () =>\r\n            {\r\n                await runOnUpdateThreadAsync(() => pendingRequests.Clear(), cancellationSource.Token).ConfigureAwait(false);\r\n                var multiplayerRoom = await CreateRoomInternal(new MultiplayerRoom(room)).ConfigureAwait(false);\r\n                await setupJoinedRoom(room, multiplayerRoom, cancellationSource.Token).ConfigureAwait(false);\r\n            }, cancellationSource.Token).ConfigureAwait(false);\r\n        }\r\n\r\n        /// <summary>\r\n        /// Joins the <see cref=\"MultiplayerRoom\"/> for a given API <see cref=\"Room\"/>.\r\n        /// </summary>\r\n        /// <param name=\"room\">The API <see cref=\"Room\"/>.</param>\r\n        /// <param name=\"password\">An optional password to use for the join operation.</param>\r\n        /// <exception cref=\"InvalidOperationException\">If the current user is already in another room, or <paramref name=\"room\"/> does not represent an active room.</exception>\r\n        public async Task JoinRoom(Room room, string? password = null)\r","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/ppy/osu/blob/d9c73e12adff2feaae4a3e158d36fe5883faf6ca/osu.Game/Online/Multiplayer/MultiplayerClient.cs#L222-L258","documentation":"Thrown by MultiplayerClient.CreateRoom when the Room property is already non-null. The client models the user as being in at most one room at a time, so a second create is a logic error.","triggerScenarios":"Calling CreateRoom(room) while already joined to a room (Room != null) without first calling LeaveRoom(). Common in UI flows where the create button can be triggered twice or before a prior join fully tears down.","commonSituations":"Double-click on the create-room button; create invoked immediately after joining a room without leaving; stale room state after an unclean disconnect where Room was not cleared.","solutions":["Call LeaveRoom() (and await its completion) before invoking CreateRoom.","Guard the call: if (client.Room != null) await client.LeaveRoom().","Disable the create-room control while client.Room != null and re-enable only after LeaveRoom resolves."],"exampleFix":"// before\nawait client.CreateRoom(room);\n\n// after\nif (client.Room != null)\n    await client.LeaveRoom();\nawait client.CreateRoom(room);","handlingStrategy":"validation","validationCode":"if (client.Room != null)\n    await client.LeaveRoom();\nawait client.CreateRoom(room);","typeGuard":null,"tryCatchPattern":"try { await client.CreateRoom(room); }\ncatch (InvalidOperationException) { /* already in a room: leave then retry once */ }","preventionTips":["Treat client.Room as the single source of truth for occupancy.","Disable create-room UI while Room != null.","Always leave before creating in room-transition flows."],"tags":["multiplayer","state-machine","room","invalid-operation"],"backgroundTag":null,"analyzedSha":"d9c73e12adff2feaae4a3e158d36fe5883faf6ca","analyzedAt":"2026-08-13T14:12:54.015Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}