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

  1. Check the JoinError payload to find the panic message and location; fix the unwrap/panic inside the writer task.
  2. Verify disk space and write permissions for part_path before starting the download.
  3. Guard slicing like &segment_data[payload_start..] with length checks to avoid panics.
  4. 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

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


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)