From 1c8a25cff981e0bd184b2beb86e246b78b4a7048 Mon Sep 17 00:00:00 2001 From: Broque Thomas <26755000+Nezreka@users.noreply.github.com> Date: Thu, 16 Apr 2026 08:43:16 -0700 Subject: [PATCH] Fix 'Delete File Too' silently failing when file path cannot be resolved MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the DB stored a path the resolver couldn't map to a local file (common with Navidrome virtual paths or Docker path mismatches), file deletion was silently skipped — the DB record was removed but the file stayed on disk with no indication to the user. Now logs the resolution failure with the stored path, returns a file_error in the API response, and the frontend shows a warning toast explaining the file wasn't deleted plus a second toast with the specific reason (e.g. Navidrome 'Report Real Path' instructions). --- web_server.py | 10 +++++++++- webui/static/script.js | 13 +++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/web_server.py b/web_server.py index 952d9108..ebf25f6d 100644 --- a/web_server.py +++ b/web_server.py @@ -14621,6 +14621,7 @@ def library_delete_track(track_id): track_info = cursor.fetchone() # Delete file from disk if requested + file_error = None if delete_file and track_info and track_info['file_path']: resolved = _resolve_library_file_path(track_info['file_path']) if resolved and os.path.exists(resolved): @@ -14630,6 +14631,10 @@ def library_delete_track(track_id): logger.info(f"Deleted file from disk: {resolved}") except Exception as e: logger.warning(f"Failed to delete file: {e}") + file_error = str(e) + else: + logger.warning(f"Could not resolve file path for deletion: {track_info['file_path']} (resolved={resolved})") + file_error = _get_file_not_found_error(track_info['file_path']) # Add to blacklist if requested if add_blacklist and track_info and track_info['file_path']: @@ -14651,7 +14656,10 @@ def library_delete_track(track_id): if cursor.rowcount == 0: return jsonify({"success": False, "error": "Track not found"}), 404 - return jsonify({"success": True, "deleted_count": cursor.rowcount, "file_deleted": file_deleted, "blacklisted": blacklisted}) + result = {"success": True, "deleted_count": cursor.rowcount, "file_deleted": file_deleted, "blacklisted": blacklisted} + if delete_file and not file_deleted and file_error: + result["file_error"] = file_error + return jsonify(result) except Exception as e: print(f"Error deleting track {track_id}: {e}") import traceback diff --git a/webui/static/script.js b/webui/static/script.js index b5c34170..f5069d10 100644 --- a/webui/static/script.js +++ b/webui/static/script.js @@ -46295,9 +46295,18 @@ async function deleteLibraryTrack(trackId, albumId) { if (!result.success) throw new Error(result.error); let msg = 'Track removed from library'; - if (result.file_deleted) msg = 'Track deleted from library and disk'; + let toastType = 'success'; + if (result.file_deleted) { + msg = 'Track deleted from library and disk'; + } else if (result.file_error) { + msg = 'Track removed from library but file could not be deleted'; + toastType = 'warning'; + } if (result.blacklisted) msg += ' (source blacklisted)'; - showToast(msg, 'success'); + showToast(msg, toastType); + if (result.file_error) { + showToast(result.file_error, 'error', 8000); + } if (artistDetailPageState.enhancedData) { const albums = artistDetailPageState.enhancedData.albums || [];