{"record":{"id":"3c5b10226d925021","repo":"tonhowtf/omniget","slug":"download-cancelled-ytdlp","errorCode":null,"errorMessage":"Download cancelled","messagePattern":"Download cancelled","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"src-tauri/omniget-core/src/core/ytdlp.rs","lineNumber":3372,"sourceCode":"        }\n        args\n    } else {\n        Vec::new()\n    };\n\n    let max_attempts: usize = 3;\n    let mut extra_args: Vec<String> = Vec::new();\n    let mut last_error = String::new();\n    let mut use_subtitles = should_download_subs;\n    let mut use_cfb = !cfb_setting.is_empty() && !explicit_cookie_header && !manual_cookie_enabled;\n    let mut format_already_simplified = false;\n    let mut last_was_429 = false;\n\n    for attempt in 0..max_attempts {\n        tracing::info!(\"[yt-dlp] download attempt {}/{}\", attempt + 1, max_attempts);\n        if cancel_token.is_cancelled() {\n            tracing::debug!(\"[perf] download_video took {:?}\", _timer_start.elapsed());\n            anyhow::bail!(\"Download cancelled\");\n        }\n\n        if attempt > 0 {\n            let wait: u64 = if last_was_429 {\n                match attempt {\n                    1 => 3,\n                    2 => 8,\n                    _ => 15,\n                }\n            } else {\n                1\n            };\n            tracing::info!(\n                \"[yt-dlp] retry {}/{} after {}s (429={})\",\n                attempt,\n                max_attempts - 1,\n                wait,\n                last_was_429","sourceCodeStart":3354,"sourceCodeEnd":3390,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/ytdlp.rs#L3354-L3390","documentation":"download_video checks a cancellation token at the start of each retry attempt and bails with \"Download cancelled\" if it is already cancelled. This is the cooperative-cancellation path: the user or app requested the download to stop.","triggerScenarios":"Calling download_video with a cancel_token that gets cancelled before or between retry attempts — user pressed stop/cancel, app shutdown, or a stale token reused from a previous cancelled operation.","commonSituations":"User cancels via UI; app teardown cancels all tokens; caller accidentally shares/reuses a token already cancelled for another download.","solutions":["Treat this as an expected control-flow outcome — catch it and surface 'cancelled' to the user, not as a failure.","If unintentional, ensure each download gets its own CancellationToken and don't reuse cancelled ones.","Check no code path cancels the token prematurely (e.g., timeout wrappers or app-close handlers)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// before starting, ensure the token is fresh\nif cancel_token.is_cancelled() {\n    cancel_token = CancellationToken::new();\n}","typeGuard":null,"tryCatchPattern":"match download_video(url, &cancel_token, ...).await {\n    Err(e) if e.to_string() == \"Download cancelled\" => {\n        tracing::info!(\"download cancelled by user\"); // not an error for the user\n    }\n    Err(e) => return Err(e),\n    Ok(v) => Ok(v),\n}","preventionTips":["Give each download its own CancellationToken; never reuse cancelled tokens.","Distinguish 'cancelled' errors from real failures in error handling paths.","Cancel tokens only from explicit user/UI actions or orderly shutdown."],"tags":["cancellation","download","control-flow"],"backgroundTag":"operation-cancelled","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}