ppy/osu · error · InvalidOperationException
Local user is not the room host.
Error message
Local user is not the room host.
What it means
AddUserPlaylistItem enforces server-side authorization: when the room's QueueMode is HostOnly, only the room host may add playlist items, otherwise it throws. This mirrors the real multiplayer server's host-only queue rule.
Source
Thrown at osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs:544
ChangeUserState(LocalUser.UserID, MultiplayerUserState.Idle);
return Task.CompletedTask;
}
public override async Task AbortMatch()
{
ChangeUserState(api.LocalUser.Value.Id, MultiplayerUserState.Idle);
await ((IMultiplayerClient)this).GameplayAborted(GameplayAbortReason.HostAbortedTheMatch).ConfigureAwait(false);
}
public async Task AddUserPlaylistItem(int userId, MultiplayerPlaylistItem item)
{
Debug.Assert(ServerRoom != null);
Debug.Assert(currentItem != null);
if (ServerRoom.Settings.QueueMode == QueueMode.HostOnly && ServerRoom.Host?.UserID != LocalUser?.UserID)
throw new InvalidOperationException("Local user is not the room host.");
item.OwnerID = userId;
await addItem(item).ConfigureAwait(false);
await updateCurrentItem(ServerRoom).ConfigureAwait(false);
updateRoomStateIfRequired();
}
public override Task AddPlaylistItem(MultiplayerPlaylistItem item) => AddUserPlaylistItem(api.LocalUser.Value.OnlineID, clone(item));
public async Task EditUserPlaylistItem(int userId, MultiplayerPlaylistItem item)
{
Debug.Assert(ServerRoom != null);
Debug.Assert(currentItem != null);
Debug.Assert(ServerAPIRoom != null);
item.OwnerID = userId;
View on GitHub (pinned to d9c73e12ad)
Solutions
- Make the acting user the host before adding (e.g. TransferHost(localUserId)).
- Switch QueueMode to AllPlayers or PlayerOnly so any user can add.
- Call AddUserPlaylistItem with the host user's id instead of the non-host's.
Example fix
// before client.ChangeSettings(queueMode: QueueMode.HostOnly); await client.AddPlaylistItem(item); // non-host throws // after client.TransferHost(localUserId); await client.AddPlaylistItem(item);
Defensive patterns
Strategy: validation
Validate before calling
if (ServerRoom.Settings.QueueMode == QueueMode.HostOnly
&& ServerRoom.Host?.UserID != LocalUser?.UserID)
{
client.TransferHost(api.LocalUser.Value.OnlineID);
}
await client.AddPlaylistItem(item); Prevention
- Before adding items under HostOnly, ensure the actor is host or switch QueueMode.
- In multi-user tests, add via the host client only.
- Centralize playlist-add helpers that check QueueMode + host first.
When it happens
Trigger: Calling AddPlaylistItem/AddUserPlaylistItem while QueueMode == HostOnly and the local user is not ServerRoom.Host (LocalUser?.UserID != ServerRoom.Host?.UserID).
Common situations: Test sets QueueMode.HostOnly but performs the add as a non-host user; the acting user id was never made host; multi-user test where the wrong client adds.
Related errors
- Attempted to change an item which is not owned by the user.
- Attempted to remove an item which is not owned by the user.
- Accessing the client-side API room via {nameof(TestMultiplay
- Accessing the client-side room via {nameof(TestMultiplayerCl
- Already joined a room
AI-assisted analysis of ppy/osu@d9c73e12ad (2026-08-13).
Data as JSON: /api/errors/f25c2ecf9305a26c.
Report an issue: GitHub.