{"record":{"id":"32bc45e882bebb93","repo":"ppy/osu","slug":"attempted-to-change-an-item-which-is-not-owned-by","errorCode":null,"errorMessage":"Attempted to change an item which is not owned by the user.","messagePattern":"Attempted to change an item which is not owned by the user\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs","lineNumber":569,"sourceCode":"        }\r\n\r\n        public override Task AddPlaylistItem(MultiplayerPlaylistItem item) => AddUserPlaylistItem(api.LocalUser.Value.OnlineID, clone(item));\r\n\r\n        public async Task EditUserPlaylistItem(int userId, MultiplayerPlaylistItem item)\r\n        {\r\n            Debug.Assert(ServerRoom != null);\r\n            Debug.Assert(currentItem != null);\r\n            Debug.Assert(ServerAPIRoom != null);\r\n\r\n            item.OwnerID = userId;\r\n\r\n            var existingItem = ServerRoom.Playlist.SingleOrDefault(i => i.ID == item.ID);\r\n\r\n            if (existingItem == null)\r\n                throw new InvalidOperationException(\"Attempted to change an item that doesn't exist.\");\r\n\r\n            if (existingItem.OwnerID != userId && ServerRoom.Host?.UserID != LocalUser?.UserID)\r\n                throw new InvalidOperationException(\"Attempted to change an item which is not owned by the user.\");\r\n\r\n            if (existingItem.Expired)\r\n                throw new InvalidOperationException(\"Attempted to change an item which has already been played.\");\r\n\r\n            // Ensure the playlist order doesn't change.\r\n            item.PlaylistOrder = existingItem.PlaylistOrder;\r\n\r\n            ServerRoom.Playlist[ServerRoom.Playlist.IndexOf(existingItem)] = item;\r\n            ServerAPIRoom.Playlist = ServerAPIRoom.Playlist.Select((pi, i) => pi.ID == item.ID ? new PlaylistItem(item) : ServerAPIRoom.Playlist[i]).ToArray();\r\n\r\n            await ((IMultiplayerClient)this).PlaylistItemChanged(clone(item)).ConfigureAwait(false);\r\n        }\r\n\r\n        public override Task EditPlaylistItem(MultiplayerPlaylistItem item) => EditUserPlaylistItem(api.LocalUser.Value.OnlineID, clone(item));\r\n\r\n        public async Task RemoveUserPlaylistItem(int userId, long playlistItemId)\r\n        {\r\n            Debug.Assert(ServerRoom != null);\r","sourceCodeStart":551,"sourceCodeEnd":587,"githubUrl":"https://github.com/ppy/osu/blob/d9c73e12adff2feaae4a3e158d36fe5883faf6ca/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs#L551-L587","documentation":"EditUserPlaylistItem requires the editor be the item's owner OR the room host; editing another user's item without host privileges throws. This mirrors the server's ownership authorization on playlist edits.","triggerScenarios":"Editing an item whose OwnerID differs from the acting userId while ServerRoom.Host?.UserID is also not the acting user.","commonSituations":"Test edits as a different user than the one who added the item; the host carve-out was assumed but the acting user is not host.","solutions":["Edit the item as the user who owns it (item.OwnerID).","Act as the room host (TransferHost) before editing another user's item.","Re-create the item under the acting user if ownership transfer is not intended."],"exampleFix":"// before\nawait client.EditUserPlaylistItem(nonOwnerUserId, item);\n\n// after\nawait client.EditUserPlaylistItem(item.OwnerID, item);\n// or make the actor host first:\nclient.TransferHost(actorUserId);\nawait client.EditUserPlaylistItem(actorUserId, item);","handlingStrategy":"validation","validationCode":"var existing = ServerRoom.Playlist.Single(i => i.ID == item.ID);\nif (existing.OwnerID != userId && ServerRoom.Host?.UserID != userId)\n    throw new InvalidOperationException(\"not owner and not host\");\nawait client.EditUserPlaylistItem(userId, item);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Edit items as their OwnerID user, or as the host.","Track which user added each item in multi-user tests.","Use TransferHost when a non-owner must modify another's item."],"tags":["test-infra","multiplayer","authorization","ownership"],"backgroundTag":null,"analyzedSha":"d9c73e12adff2feaae4a3e158d36fe5883faf6ca","analyzedAt":"2026-08-13T14:12:54.015Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}