peter
cdcffb8c91
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.
2026-07-28 01:40:22 +02:00
..
2026-07-21 02:26:40 +02:00
2026-07-18 19:11:25 +02:00
2026-07-27 22:10:03 +02:00
2026-07-27 21:48:35 +02:00
2026-07-18 00:35:57 +02:00
2026-07-27 21:48:35 +02:00
2026-07-27 22:10:03 +02:00
2026-07-20 22:17:51 +02:00
2026-07-27 22:10:03 +02:00
2026-06-12 18:01:43 +02:00
2026-07-21 02:26:40 +02:00
2026-07-21 02:26:40 +02:00
2026-07-21 02:26:40 +02:00
2026-07-21 02:26:40 +02:00
2026-07-27 21:48:35 +02:00
2026-07-21 02:26:40 +02:00
2026-06-19 03:22:10 +02:00
2026-07-27 21:48:35 +02:00
2026-07-27 21:48:35 +02:00
2026-07-27 21:48:35 +02:00
2026-07-21 02:26:40 +02:00
2026-07-27 22:10:03 +02:00
2026-07-27 22:10:03 +02:00
2026-07-21 02:26:40 +02:00
2026-07-27 22:10:03 +02:00
2026-07-21 02:26:40 +02:00
2026-07-22 04:14:46 +02:00
2026-06-19 11:18:20 +02:00
2026-07-27 22:10:03 +02:00
2026-07-28 01:40:22 +02:00
2026-07-27 22:10:03 +02:00
2026-07-21 02:26:40 +02:00
2026-06-18 01:17:31 +02:00
2026-07-27 22:40:11 +02:00
2026-07-27 22:10:03 +02:00
2026-07-27 22:10:03 +02:00
2026-07-21 04:11:19 +02:00
2026-07-19 00:08:34 +02:00
2026-07-27 22:10:03 +02:00
2026-07-21 02:26:40 +02:00
2026-07-27 22:10:03 +02:00
2026-07-21 23:13:53 +02:00
2026-07-13 02:28:06 +02:00
2026-07-19 01:25:32 +02:00
2026-07-21 02:26:40 +02:00
2026-07-27 22:10:03 +02:00
2026-07-27 22:57:33 +02:00
2026-07-27 21:48:35 +02:00
2026-07-18 19:11:38 +02:00
2026-07-20 01:10:13 +02:00
2026-07-18 05:43:19 +02:00
2026-07-18 05:43:19 +02:00
2026-07-21 02:26:40 +02:00
2026-07-21 22:29:39 +02:00
2026-07-27 22:57:33 +02:00
2026-07-21 00:03:07 +02:00
2026-07-27 21:48:35 +02:00
2026-07-21 02:26:40 +02:00
2026-07-27 21:48:35 +02:00
2026-07-27 22:10:03 +02:00
2026-07-27 22:10:03 +02:00
2026-07-27 22:10:03 +02:00
2026-07-27 22:57:33 +02:00
2026-07-27 22:10:03 +02:00
2026-07-27 22:10:03 +02:00
2026-07-21 02:26:40 +02:00
2026-07-27 22:10:03 +02:00
2026-07-27 22:10:03 +02:00
2026-07-27 22:10:03 +02:00
2026-07-22 04:35:02 +02:00
2026-07-22 00:00:44 +02:00
2026-07-27 21:48:35 +02:00
2026-07-27 22:10:03 +02:00
2026-07-13 02:28:06 +02:00
2026-07-27 22:57:33 +02:00
2026-07-27 22:57:33 +02:00
2026-07-28 01:21:50 +02:00
2026-07-27 21:48:35 +02:00
2026-07-18 19:11:25 +02:00
2026-07-27 22:10:03 +02:00
2026-07-27 21:48:35 +02:00
2026-07-21 02:26:40 +02:00
2026-07-02 01:45:16 +02:00
2026-07-27 21:48:35 +02:00
2026-07-21 23:36:27 +02:00
2026-07-21 02:26:40 +02:00
2026-07-21 02:26:40 +02:00
2026-06-19 11:18:20 +02:00
2026-07-27 22:40:11 +02:00
2026-07-27 22:10:03 +02:00
2026-07-21 02:26:40 +02:00
2026-07-27 22:40:11 +02:00
2026-07-21 02:26:40 +02:00
2026-07-21 02:26:40 +02:00
2026-07-23 01:24:34 +02:00
2026-07-27 22:10:03 +02:00