tonhowtf/omniget · error · anyhow::Error
Writer task panicked
Error message
Writer task panicked: {:?} What it means
Segments are written to the output part file by a spawned tokio task; download_media_playlist awaits its JoinHandle. If the writer task panicked (JoinError), this error is raised. A panic in the writer typically stems from an I/O bug or an unwrap inside the task, and it means the part file is incomplete.
Solutions
- Check the JoinError payload to find the panic message and location; fix the unwrap/panic inside the writer task.
- Verify disk space and write permissions for part_path before starting the download.
- Guard slicing like &segment_data[payload_start..] with length checks to avoid panics.
- Clean up the part file and restart the download after fixing; the partial file is unusable.
Example fix
// before
let writer_result = writer.await
.map_err(|e| anyhow::anyhow!("Writer task panicked: {:?}", e))?;
// after
let writer_result = writer.await.map_err(|e| {
let _ = std::fs::remove_file(&part_path);
anyhow::anyhow!("Writer task panicked: {e:?}")
})?;
if let Err(e) = writer_result {
let _ = std::fs::remove_file(&part_path);
return Err(e);
} Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check destination writability/space before spawning writer
let probe = std::fs::OpenOptions::new().write(true).create(true).open(&part_path);
if let Err(e) = probe { anyhow::bail!("cannot write part file: {e}"); } Try / catch
match writer.await {
Ok(Ok(())) => { /* success */ }
Ok(Err(e)) => { let _ = std::fs::remove_file(&part_path); bail!("writer io error: {e}"); }
Err(join_err) => {
let _ = std::fs::remove_file(&part_path);
bail!("writer task panicked: {join_err:?}");
}
}; Prevention
- Avoid unwrap()/expect() inside spawned writer tasks; return Results.
- Check payload_start <= segment_data.len() before slicing.
- Monitor disk space for long HLS downloads.
- Delete the part file on any writer failure so restarts begin clean.
When it happens
Trigger: writer JoinHandle resolves with Err(JoinError) because the task panicked — e.g., unwrap on a poisoned mutex, file write returning an unexpected state, or an index bug on segment payloads.
Common situations: Disk full or file handle issues surfacing as a panic inside the writer; bug in segment ordering code (payload_start beyond buffer length); tokio runtime shutdown mid-task.
Related errors
- spawn_blocking failed
- Spawn blocking failed
- worker task panicked
- spawn_blocking failed
- tarefa de remoção de fundo falhou
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/f852c5df6c978b75.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/core/hls_downloader.rs:399
Err(e) => {
let key = e.to_string();
let mut errs = errors_ref.lock().await;
*errs.entry(key).or_insert(0) += 1;
drop(errs);
fail_ref.cancel();
}
}
}
})
.buffer_unordered(max_concurrent as usize)
.collect::<()>()
.await;
drop(seg_tx);
let writer_result = writer
.await
.map_err(|e| anyhow::anyhow!("Writer task panicked: {:?}", e))?;
if cancel_token.is_cancelled() {
let _ = std::fs::remove_file(&part_path);
anyhow::bail!("Download cancelled by user");
}
let errs = errors.lock().await;
if !errs.is_empty() {
let _ = std::fs::remove_file(&part_path);
let summary: Vec<String> = errs
.iter()
.map(|(msg, count)| {
if *count > 1 {
format!("{} (x{})", msg, count)
} else {
msg.clone()
}
})View on GitHub (pinned to 8600b91f42)