ppy/osu · error · InvalidOperationException
Must be joined to a match to change settings.
Error message
Must be joined to a match to change settings.
What it means
Thrown by MultiplayerClient.ChangeSettings when Room is null, meaning the local user is not currently joined to a match. Settings can only be changed against an active joined room.
Source
Thrown at osu.Game/Online/Multiplayer/MultiplayerClient.cs:411
/// <summary>
/// Change the current <see cref="MultiplayerRoom"/> settings.
/// </summary>
/// <remarks>
/// A room must be joined for this to have any effect.
/// </remarks>
/// <param name="name">The new room name, if any.</param>
/// <param name="password">The new password, if any.</param>
/// <param name="matchType">The type of the match, if any.</param>
/// <param name="queueMode">The new queue mode, if any.</param>
/// <param name="autoStartDuration">The new auto-start countdown duration, if any.</param>
/// <param name="autoSkip">The new auto-skip setting.</param>
/// <param name="maxParticipants">The new participant count limit, if any.</param>
public Task ChangeSettings(Optional<string> name = default, Optional<string> password = default, Optional<MatchType> matchType = default, Optional<QueueMode> queueMode = default,
Optional<TimeSpan> autoStartDuration = default, Optional<bool> autoSkip = default, Optional<byte?> maxParticipants = default)
{
if (Room == null)
throw new InvalidOperationException("Must be joined to a match to change settings.");
return ChangeSettings(new MultiplayerRoomSettings
{
Name = name.GetOr(Room.Settings.Name),
Password = password.GetOr(Room.Settings.Password),
MatchType = matchType.GetOr(Room.Settings.MatchType),
QueueMode = queueMode.GetOr(Room.Settings.QueueMode),
AutoStartDuration = autoStartDuration.GetOr(Room.Settings.AutoStartDuration),
AutoSkip = autoSkip.GetOr(Room.Settings.AutoSkip),
MaxParticipants = maxParticipants.GetOr(Room.Settings.MaxParticipants),
});
}
/// <summary>
/// Toggles the <see cref="LocalUser"/>'s ready state.
/// </summary>
/// <exception cref="InvalidOperationException">If a toggle of ready state is not valid at this time.</exception>
public async Task ToggleReady()
View on GitHub (pinned to d9c73e12ad)
Solutions
- Ensure the client is joined (client.Room != null) before invoking ChangeSettings.
- Re-acquire the room reference or re-join if Room is null.
- Disable settings editing controls when client.Room == null.
Example fix
// before await client.ChangeSettings(name: "New Name"); // after if (client.Room == null) return; await client.ChangeSettings(name: "New Name");
Defensive patterns
Strategy: validation
Validate before calling
if (client.Room == null) return; await client.ChangeSettings(name: newName);
Type guard
bool CanEditSettings(MultiplayerClient c) => c.Room != null;
Try / catch
try { await client.ChangeSettings(settings); }
catch (InvalidOperationException) { /* not joined: ignore or re-prompt join */ } Prevention
- Bind settings-edit controls to client.Room != null.
- Re-check Room immediately before the call (it can clear on disconnect).
- Handle Room-cleared events to disable editing.
When it happens
Trigger: Calling ChangeSettings(...) before JoinRoom completes, or after the client has been disconnected/parted (Room cleared). The convenience overload builds a MultiplayerRoomSettings from Room.Settings and needs Room to exist.
Common situations: Race between leaving a room and a pending settings edit; UI letting the host edit settings after a kick/disconnect; calling ChangeSettings on a client that never joined.
Related errors
- Cannot create a multiplayer room while already in one.
- Cannot join a multiplayer room while already in one.
- Cannot toggle ready when in {localUser.State}
- Cannot toggle spectate when in {localUser.State}
- Cannot join an inactive room.
AI-assisted analysis of ppy/osu@d9c73e12ad (2026-08-13).
Data as JSON: /api/errors/3735c0b233058147.
Report an issue: GitHub.