feat(downloads): categorize download failures + a readable error dialog (S2)

Failed downloads stored the raw yt-dlp/ffmpeg text and dumped it as a truncated red
one-liner in the queue. Classify the failure into a category (unavailable / login_required /
geo_blocked / format_unavailable / drm / postprocess / source_missing / network / unknown)
and surface it properly:

- backend: app/downloads/errors.classify maps the raw message to a category code; the worker
  stores it in the new download_jobs.error_code (migration 0061) at both failure sites; resume
  clears it; the serializer exposes it. Raw text kept as technical detail.
- frontend: the queue row shows a clean localized reason + a "details" link opening a modal
  with the explanation, the raw text behind a disclosure, and a Retry only for transient
  categories (network/postprocess/unknown).
- tests: classify() unit coverage over verbatim yt-dlp/ffmpeg message shapes.
This commit is contained in:
2026-07-28 01:40:22 +02:00
parent 3f15f35256
commit cdcffb8c91
10 changed files with 337 additions and 5 deletions
+2 -1
View File
@@ -69,7 +69,8 @@ export interface DownloadJob {
speed_bps: number | null;
eta_s: number | null;
phase: string | null;
error: string | null;
error: string | null; // raw yt-dlp/ffmpeg text (technical detail)
error_code: string | null; // failure category, see backend downloads.errors.classify
queue_pos: number;
created_at: string | null;
source_kind: string;