ppy/osu · error · InvalidOperationException
Cannot create a multiplayer room while already in one.
Error message
Cannot create a multiplayer room while already in one.
What it means
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.
Source
Thrown at osu.Game/Online/Multiplayer/MultiplayerClient.cs:240
LeaveRoom().FireAndForget();
MatchmakingQueueLeft?.Invoke();
}
}));
}
private readonly TaskChain joinOrLeaveTaskChain = new TaskChain();
private CancellationTokenSource? joinCancellationSource;
/// <summary>
/// Creates and joins a <see cref="MultiplayerRoom"/> described by an API <see cref="Room"/>.
/// </summary>
/// <param name="room">The API <see cref="Room"/> describing the room to create.</param>
/// <exception cref="InvalidOperationException">If the current user is already in another room.</exception>
public async Task CreateRoom(Room room)
{
if (Room != null)
throw new InvalidOperationException("Cannot create a multiplayer room while already in one.");
var cancellationSource = joinCancellationSource = new CancellationTokenSource();
await joinOrLeaveTaskChain.Add(async () =>
{
await runOnUpdateThreadAsync(() => pendingRequests.Clear(), cancellationSource.Token).ConfigureAwait(false);
var multiplayerRoom = await CreateRoomInternal(new MultiplayerRoom(room)).ConfigureAwait(false);
await setupJoinedRoom(room, multiplayerRoom, cancellationSource.Token).ConfigureAwait(false);
}, cancellationSource.Token).ConfigureAwait(false);
}
/// <summary>
/// Joins the <see cref="MultiplayerRoom"/> for a given API <see cref="Room"/>.
/// </summary>
/// <param name="room">The API <see cref="Room"/>.</param>
/// <param name="password">An optional password to use for the join operation.</param>
/// <exception cref="InvalidOperationException">If the current user is already in another room, or <paramref name="room"/> does not represent an active room.</exception>
public async Task JoinRoom(Room room, string? password = null)
View on GitHub (pinned to d9c73e12ad)
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.
Example fix
// before
await client.CreateRoom(room);
// after
if (client.Room != null)
await client.LeaveRoom();
await client.CreateRoom(room); Defensive patterns
Strategy: validation
Validate before calling
if (client.Room != null)
await client.LeaveRoom();
await client.CreateRoom(room); Try / catch
try { await client.CreateRoom(room); }
catch (InvalidOperationException) { /* already in a room: leave then retry once */ } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Cannot join a multiplayer room while already in one.
- Cannot join an inactive room.
- Must be joined to a match to change settings.
- Cannot toggle ready when in {localUser.State}
- Cannot toggle spectate when in {localUser.State}
AI-assisted analysis of ppy/osu@d9c73e12ad (2026-08-13).
Data as JSON: /api/errors/5a4ce968b16adf5a.
Report an issue: GitHub.