{"record":{"id":"ba2af8bcbf0faee2","repo":"tonhowtf/omniget","slug":"download-cancelled-mod","errorCode":null,"errorMessage":"Download cancelled","messagePattern":"Download cancelled","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"src-tauri/src/platforms/gallerydl/mod.rs","lineNumber":287,"sourceCode":"        });\n\n        let stderr_task = tokio::spawn(async move {\n            let mut buf = String::new();\n            let mut lines = BufReader::new(stderr_pipe).lines();\n            while let Ok(Some(line)) = lines.next_line().await {\n                buf.push_str(&line);\n                buf.push('\\n');\n            }\n            buf\n        });\n\n        let status = tokio::select! {\n            s = child.wait() => s.map_err(|e| anyhow!(\"gallery-dl process failed: {}\", e))?,\n            _ = opts.cancel_token.cancelled() => {\n                let _ = child.kill().await;\n                let _ = reader_task.await;\n                let _ = stderr_task.await;\n                anyhow::bail!(\"Download cancelled\");\n            }\n        };\n\n        let _ = reader_task.await;\n        let stderr_content = stderr_task.await.unwrap_or_default();\n\n        if !status.success() {\n            let detail = stderr_content\n                .lines()\n                .rev()\n                .find(|l| {\n                    let l = l.to_lowercase();\n                    l.contains(\"error\")\n                        || l.contains(\"forbidden\")\n                        || l.contains(\"not found\")\n                        || l.contains(\"unsupported\")\n                })\n                .unwrap_or(\"gallery-dl failed\")","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/src/platforms/gallerydl/mod.rs#L269-L305","documentation":"The gallery-dl wrapper spawns the gallery-dl process and selects between child.wait() and the cancel token's cancelled() future. On cancellation it kills the child, drains stdout/stderr tasks, and bails with 'Download cancelled'.","triggerScenarios":"Signalling opts.cancel_token while a gallery-dl child process is running (waiting for it to exit); calling download and cancelling before the process finishes.","commonSituations":"User aborts a gallery-based download mid-run; app shutdown cancels all tokens; UI timeout cancels a slow gallery-dl fetch.","solutions":["Treat as expected abort: catch the error, report partial files already written, and clean temp dirs.","If pausing is intended, add a pause mechanism instead of cancelling the token.","Avoid sharing one cancel token across unrelated downloads if only one should stop."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if opts.cancel_token.is_cancelled() {\n    return Err(anyhow!(\"Download cancelled\")); // skip spawning gallery-dl\n}","typeGuard":null,"tryCatchPattern":"match download(url, opts).await {\n    Err(e) if e.to_string() == \"Download cancelled\" => {\n        cleanup_partial_output(&out_dir);\n    }\n    other => other?,\n}","preventionTips":["Scope cancel tokens per download so aborting one doesn't kill others","Track already-downloaded files for resume","Distinguish user cancellation from process failure in logs"],"tags":["gallery-dl","cancellation","process","async"],"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"}