{"record":{"id":"363f2cba41678af8","repo":"tonhowtf/omniget","slug":"worker-task-panicked","errorCode":null,"errorMessage":"worker task panicked: {:?}","messagePattern":"worker task panicked: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/http_fetcher.rs","lineNumber":545,"sourceCode":"            let cfg = self.config.clone();\n            tasks.push(tokio::spawn(async move {\n                worker_loop(client, url, headers, part_path, segments, cancel, cfg).await\n            }));\n        }\n\n        let mut first_err: Option<anyhow::Error> = None;\n        for t in tasks {\n            match t.await {\n                Ok(Ok(())) => {}\n                Ok(Err(e)) => {\n                    if first_err.is_none() {\n                        first_err = Some(e);\n                    }\n                    cancel.cancel();\n                }\n                Err(e) => {\n                    if first_err.is_none() {\n                        first_err = Some(anyhow!(\"worker task panicked: {:?}\", e));\n                    }\n                    cancel.cancel();\n                }\n            }\n        }\n\n        progress_pump.abort();\n        if let Some(p) = resume_pump {\n            p.abort();\n        }\n        let _ = progress_pump.await;\n\n        if let Some(e) = first_err {\n            return Err(e);\n        }\n\n        let segs = segments.lock().await;\n        let all_done = segs","sourceCodeStart":527,"sourceCodeEnd":563,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/http_fetcher.rs#L527-L563","documentation":"download_chunked spawns per-segment worker tasks and joins them; if a worker task itself panicked (rather than returning Err), the JoinHandle resolves with a JoinError. The fetcher wraps that panic in an anyhow error carrying the panic payload, cancels all other segments, and aborts the download. It signals a bug or abort inside worker code, not a network failure.","triggerScenarios":"A tokio worker task spawned by download_chunked panics — e.g. a slice index out of bounds on a segment range, unwrap() on a None state, or an explicit panic!/assertion inside worker_loop/download_segment — and the .join() future resolves to Err(JoinError).","commonSituations":"Panic on unusual Content-Range responses (negative/overflowing byte offsets), bugs in retry-state bookkeeping, or task aborts surfacing as JoinError::is_cancelled after a runtime shutdown.","solutions":["Reproduce with the panic payload from `{:?}` (it names the panic message and source location) and fix the panicking code in worker_loop/download_segment.","Check byte-offset arithmetic against very large files (>4 GiB) and zero-length ranges; replace unwrap/expect with proper error returns.","If the JoinError is a cancellation, audit who is aborting tasks and ensure shutdown is graceful rather than via abort().","Wrap worker bodies with a catch_unwind or ensure all failure paths return Result so errors flow through first_err instead of panicking."],"exampleFix":"// before\nlet end = range_start + chunk_size; // can overflow/panic downstream\n// after\nlet end = range_start.saturating_add(chunk_size).min(total_len - 1);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"// Rust: inspect JoinError before trusting the payload\nfn is_panic(je: &tokio::task::JoinError) -> bool { je.is_panic() }","tryCatchPattern":"match download(...).await {\n    Err(e) if e.to_string().starts_with(\"worker task panicked\") => {\n        // bug in worker code: log payload, file a fix, restart download\n    }\n    Err(e) => { /* normal network failure path */ }\n    Ok(v) => { /* proceed */ }\n}","preventionTips":["Keep all worker failure paths on Result; avoid unwrap/expect/panic in worker_loop and download_segment.","Fuzz byte-offset math with edge-case sizes (0 bytes, >4 GiB, last tiny segment).","Run CI with panic=abort in tests so worker panics surface immediately."],"tags":["rust","tokio","panic","download"],"backgroundTag":"internal-invariant-violation","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"}