Fix library maintenance path fixes failing silently (#207)
fix_finding() was using a potentially stale transfer_folder that was only refreshed during scheduled job runs, not on manual fix attempts. Now re-reads the transfer path from config before each fix, matching the same logic used by _run_next_job(). Also surfaces fix failure reasons to the user — bulk fix now logs each failure with finding ID and error, and the frontend toast shows the actual error message instead of just "X failed".
This commit is contained in:
parent
20452859c5
commit
98463e5d43
4 changed files with 32 additions and 6 deletions
|
|
@ -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)}
|
||||
|
|
|
|||
|
|
@ -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}")
|
||||
|
|
|
|||
|
|
@ -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' },
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Reference in a new issue