diff --git a/frontend/src/lib/components/backups/BackupManager.svelte b/frontend/src/lib/components/backups/BackupManager.svelte index d77cabef..c3ebec60 100644 --- a/frontend/src/lib/components/backups/BackupManager.svelte +++ b/frontend/src/lib/components/backups/BackupManager.svelte @@ -9,13 +9,23 @@ @RELATION USES -> [EXT:frontend:api] @INVARIANT: Only one backup task can be triggered at a time from the UI. +@UX_FEEDBACK Error toast on backup creation failure (was missing — caught state hung forever). +@UX_FEEDBACK Error toast on data load failure (was missing — loading spinner stayed forever). +@UX_FEEDBACK Error toast on schedule update failure (was missing). +@UX_RECOVERY Request timeout (30s) via AbortSignal.timeout — prevents infinite spinner when backend is unreachable. +@UX_RECOVERY In-flight requests cancelled via AbortController onDestroy — prevents stale state after navigation. +@RATIONALE Fetch API has no default timeout. Without timeout, loadData() and handleCreateBackup() hang + indefinitely when backend is unreachable, leaving loading/creating=true forever. Added 30s + timeout via AbortSignal.timeout() + onDestroy cleanup + user-facing error toasts. +@REJECTED AbortController without timeout rejected — timeout is essential; abort-on-destroy alone + doesn't protect against backend that never responds. --> {#if show} +