diff --git a/core/repair_worker.py b/core/repair_worker.py index 8e45e118..ecc616ae 100644 --- a/core/repair_worker.py +++ b/core/repair_worker.py @@ -757,6 +757,11 @@ class RepairWorker: finding_id: ID of the finding to fix fix_action: Optional action override (e.g. 'staging' or 'delete' for orphan files) """ + # Refresh transfer folder from config before each fix — same logic as _run_next_job + if self._config_manager: + raw = self._config_manager.get('soulseek.transfer_path', './Transfer') + self.transfer_folder = self._resolve_path(raw) + conn = None try: conn = self.db._get_connection() @@ -2301,14 +2306,18 @@ class RepairWorker: fixed = 0 failed = 0 + errors = [] for fid in ids_to_fix: result = self.fix_finding(fid, fix_action=fix_action) if result.get('success'): fixed += 1 else: + error_msg = result.get('error', 'unknown error') + logger.warning("Fix failed for finding #%s: %s", fid, error_msg) + errors.append({'id': fid, 'error': error_msg}) failed += 1 - return {'fixed': fixed, 'failed': failed, 'total': len(ids_to_fix)} + return {'fixed': fixed, 'failed': failed, 'total': len(ids_to_fix), 'errors': errors} except Exception as e: logger.error("Error bulk fixing findings: %s", e, exc_info=True) return {'fixed': 0, 'failed': 0, 'total': 0, 'error': str(e)} diff --git a/web_server.py b/web_server.py index 66022734..c02c28ed 100644 --- a/web_server.py +++ b/web_server.py @@ -18999,6 +18999,15 @@ def get_version_info(): "title": "What's New in SoulSync", "subtitle": f"Version {SOULSYNC_VERSION} — Latest Changes", "sections": [ + { + "title": "🔧 Fix Library Maintenance Path Fixes Failing Silently", + "description": "Path mismatch fixes now use fresh config and report errors to the UI", + "features": [ + "• Transfer folder path is re-read from config before each fix attempt", + "• Fix failure reasons are now shown in the toast notification", + "• Bulk fix failures are logged individually with finding ID and error details" + ] + }, { "title": "🔧 Fix Spotify Manual Match Storing Wrong IDs", "description": "Manual match modals no longer store iTunes/Deezer IDs in Spotify ID columns", @@ -44034,7 +44043,8 @@ def repair_findings_bulk_fix(): 'success': True, 'fixed': result.get('fixed', 0), 'failed': result.get('failed', 0), - 'total': result.get('total', 0) + 'total': result.get('total', 0), + 'errors': result.get('errors', []) }), 200 except Exception as e: logger.error(f"Error bulk fixing findings: {e}") diff --git a/webui/static/helper.js b/webui/static/helper.js index 30f8443c..063d1da7 100644 --- a/webui/static/helper.js +++ b/webui/static/helper.js @@ -3403,6 +3403,7 @@ function closeHelperSearch() { const WHATS_NEW = { '2.1': [ // Newest features first + { title: 'Fix Path Mismatch Fixes', desc: 'Library Maintenance path fixes now use fresh config and show error reasons in the toast' }, { title: 'Fix Wrong Spotify IDs', desc: 'Manual match no longer stores iTunes IDs as Spotify IDs — detects actual provider from results' }, { title: 'Spotify Enrichment Budget', desc: 'Background enrichment worker caps at 3,000 items/day to prevent rate limit bans — resets at midnight' }, { title: 'Per-Artist Library Sync', desc: 'Validate files and clean stale entries per artist from the enhanced library view', page: 'library', selector: '.library-controls' }, diff --git a/webui/static/script.js b/webui/static/script.js index 2eb96bea..2fc09367 100644 --- a/webui/static/script.js +++ b/webui/static/script.js @@ -55821,7 +55821,11 @@ async function fixAllMatchingFindings() { }); const result = await response.json(); if (result.success) { - showToast(`Fixed ${result.fixed}${result.failed ? `, ${result.failed} failed` : ''} of ${result.total}`, result.fixed > 0 ? 'success' : 'error'); + let msg = `Fixed ${result.fixed}${result.failed ? `, ${result.failed} failed` : ''} of ${result.total}`; + if (result.errors && result.errors.length > 0) { + msg += `: ${result.errors[0].error}`; + } + showToast(msg, result.fixed > 0 ? 'success' : 'error'); } else { showToast(result.error || 'Bulk fix failed', 'error'); } @@ -56013,7 +56017,7 @@ async function bulkFixFindings() { if (!orphanFixAction) return; } - let fixed = 0, failed = 0; + let fixed = 0, failed = 0, lastError = ''; showToast(`Fixing ${ids.length} findings...`, 'info'); for (const id of ids) { @@ -56030,14 +56034,16 @@ async function bulkFixFindings() { }); const result = await response.json(); if (result.success) fixed++; - else failed++; + else { failed++; lastError = result.error || 'unknown error'; } } catch { failed++; } } _repairSelectedFindings.clear(); - showToast(`Fixed ${fixed}${failed ? `, ${failed} failed` : ''}`, fixed > 0 ? 'success' : 'error'); + let fixMsg = `Fixed ${fixed}${failed ? `, ${failed} failed` : ''}`; + if (failed && lastError) fixMsg += `: ${lastError}`; + showToast(fixMsg, fixed > 0 ? 'success' : 'error'); loadRepairFindingsDashboard(); loadRepairFindings(); updateRepairStatus();