From: OzGav Date: Tue, 6 Jan 2026 08:10:23 +0000 (+1000) Subject: Fix Music Assistant playlist not being removed (#2931) X-Git-Url: https://git.kitaultman.com/?a=commitdiff_plain;h=ffe04bb1827a2f9edcfd42188f1af40548fc9e63;p=music-assistant-server.git Fix Music Assistant playlist not being removed (#2931) * Fix playlist recreation issue after removal When a Music Assistant playlist was removed from the library, the config entry was correctly removed but the physical playlist file in the playlists/ directory was not deleted. This orphaned file could cause the playlist to be recreated during synchronization. This fix ensures that when a playlist is removed via library_remove(), both the config entry and the physical playlist file are deleted. Fixes the issue where playlists would reappear after sync with a new ID. * Add LIBRARY_PLAYLISTS_EDIT feature to builtin provider The builtin provider was missing ProviderFeature.LIBRARY_PLAYLISTS_EDIT, which prevented library_remove() from being called when playlists were removed from the library. This meant the playlist file cleanup code was never executed. Adding this feature ensures that: 1. library_edit_supported() returns True for playlists 2. library_remove() is called during playlist removal 3. The playlist file is properly deleted * Use playlist lock for file deletion to prevent race conditions When deleting a playlist file, we now acquire the _playlist_lock to prevent race conditions with concurrent read/write operations, consistent with _read_playlist_file_items() and _write_playlist_file_items(). --------- Co-authored-by: Claude --- diff --git a/music_assistant/providers/builtin/__init__.py b/music_assistant/providers/builtin/__init__.py index e0490e2d..b97cdfde 100644 --- a/music_assistant/providers/builtin/__init__.py +++ b/music_assistant/providers/builtin/__init__.py @@ -85,6 +85,7 @@ SUPPORTED_FEATURES = { ProviderFeature.LIBRARY_PLAYLISTS, ProviderFeature.LIBRARY_TRACKS_EDIT, ProviderFeature.LIBRARY_RADIOS_EDIT, + ProviderFeature.LIBRARY_PLAYLISTS_EDIT, ProviderFeature.PLAYLIST_CREATE, ProviderFeature.PLAYLIST_TRACKS_EDIT, } @@ -342,6 +343,11 @@ class BuiltinProvider(MusicProvider): elif media_type == MediaType.PLAYLIST: # manually added (multi provider) playlist removal key = CONF_KEY_PLAYLISTS + # also delete the playlist file if it exists + playlist_file = os.path.join(self._playlists_dir, prov_item_id) + if await asyncio.to_thread(os.path.isfile, playlist_file): + async with self._playlist_lock: + await asyncio.to_thread(os.remove, playlist_file) else: return False stored_items: list[StoredItem] = self.mass.config.get(key, [])