ppy/osu · error · InvalidOperationException
Attempted to change an item that doesn't exist.
Error message
Attempted to change an item that doesn't exist.
What it means
EditUserPlaylistItem looks up the target by item.ID in ServerRoom.Playlist (SingleOrDefault) and throws if nothing matches, reproducing the server's 'item must exist before you can edit it' precondition.
Source
Thrown at osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs:566
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;
var existingItem = ServerRoom.Playlist.SingleOrDefault(i => i.ID == item.ID);
if (existingItem == null)
throw new InvalidOperationException("Attempted to change an item that doesn't exist.");
if (existingItem.OwnerID != userId && ServerRoom.Host?.UserID != LocalUser?.UserID)
throw new InvalidOperationException("Attempted to change an item which is not owned by the user.");
if (existingItem.Expired)
throw new InvalidOperationException("Attempted to change an item which has already been played.");
// Ensure the playlist order doesn't change.
item.PlaylistOrder = existingItem.PlaylistOrder;
ServerRoom.Playlist[ServerRoom.Playlist.IndexOf(existingItem)] = item;
ServerAPIRoom.Playlist = ServerAPIRoom.Playlist.Select((pi, i) => pi.ID == item.ID ? new PlaylistItem(item) : ServerAPIRoom.Playlist[i]).ToArray();
await ((IMultiplayerClient)this).PlaylistItemChanged(clone(item)).ConfigureAwait(false);
}
public override Task EditPlaylistItem(MultiplayerPlaylistItem item) => EditUserPlaylistItem(api.LocalUser.Value.OnlineID, clone(item));
View on GitHub (pinned to d9c73e12ad)
Solutions
- Set item.ID to an existing ServerRoom.Playlist entry's ID before editing.
- Re-read the current playlist from ServerRoom.Playlist to get a valid ID.
- If the item should not exist yet, AddPlaylistItem it first instead of editing.
Example fix
// before item.ID = 999; // not in playlist await client.EditPlaylistItem(item); // after item.ID = client.ServerRoom.Playlist.First(i => !i.Expired).ID; await client.EditPlaylistItem(item);
Defensive patterns
Strategy: validation
Validate before calling
var existing = ServerRoom.Playlist.SingleOrDefault(i => i.ID == item.ID);
if (existing == null)
throw new InvalidOperationException($"no playlist item {item.ID} to edit");
await client.EditPlaylistItem(item); Prevention
- Always source the ID from ServerRoom.Playlist, never a literal.
- Re-query the playlist before editing if other steps may have mutated it.
- Prefer Add for new items rather than editing a non-existent ID.
When it happens
Trigger: Calling EditPlaylistItem/EditUserPlaylistItem with an ID that is not present in ServerRoom.Playlist (stale, removed, or never-added).
Common situations: Editing a cloned item whose ID no longer exists; the item was already removed by another step; using an arbitrary/hardcoded ID.
Related errors
- Item does not exist in the room.
- Attempted to change an item which has already been played.
- The room's current item cannot be removed.
- Attempted to remove an item which has already been played.
- Cannot join an inactive room.
AI-assisted analysis of ppy/osu@d9c73e12ad (2026-08-13).
Data as JSON: /api/errors/34e5eee933962851.
Report an issue: GitHub.