tonhowtf/omniget · error · anyhow::Error

Failed to read zip entry

Error message

Failed to read zip entry: {}

What it means

In extract_zip_ffmpeg, each entry of the downloaded FFmpeg zip archive is opened with archive.by_index(i) inside a spawn_blocking task. If the zip central/local directory entry cannot be read or decoded, the zip crate error is wrapped with anyhow into this message and propagated as an anyhow::Error through download_ffmpeg.

Solutions

  1. Delete the cached archive and re-run download_ffmpeg to get a fresh copy
  2. Verify the download URL returns a real zip (check Content-Type / magic bytes 'PK') before extraction
  3. Confirm the zip crate version supports the archive's compression method (e.g. bzip2/deflate64 features)
  4. Check disk space and that no other process holds the archive file open

Example fix

// before
let mut entry = archive
    .by_index(i)
    .map_err(|e| anyhow!("Failed to read zip entry: {}", e))?;
// after
let mut entry = archive
    .by_index(i)
    .map_err(|e| anyhow!("Failed to read zip entry {} (archive may be corrupt or incomplete; re-download): {}", i, e))?;
Defensive patterns

Strategy: try-catch

Validate before calling

let meta = std::fs::metadata(&archive_path)?;
if meta.len() < 1024 { return Err(anyhow!("Archive too small to be a valid zip")); }
let mut f = std::fs::File::open(&archive_path)?;
let mut magic = [0u8; 4];
std::io::Read::read_exact(&mut f, &mut magic)?;
if &magic != b"PK\x03\x04" { return Err(anyhow!("Not a zip file; re-download")); }

Type guard

fn looks_like_zip(bytes: &[u8]) -> bool { bytes.starts_with(b"PK\x03\x04") || bytes.starts_with(b"PK\x05\x06") }

Try / catch

match extract_zip_ffmpeg(&path, &bin_dir, &ffmpeg, &ffprobe).await {
    Ok(()) => {},
    Err(e) if e.to_string().contains("Failed to read zip entry") => {
        std::fs::remove_file(&path).ok();
        // re-download then retry once
    },
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling download_ffmpeg on a truncated, corrupt, or non-zip file whose outer reads still let by_index be attempted; zip entries with unsupported compression methods or bad local headers; I/O errors while seeking within the archive file.

Common situations: Interrupted/partial download of the FFmpeg zip; proxy or CDN serving an HTML error page saved as .zip; disk issues or antivirus locking the file mid-read; a URL change upstream now points at a different archive format.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/ee9d03928b4ce584. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/omniget-core/src/core/dependencies.rs:593

    ffprobe_name: &str,
) -> anyhow::Result<()> {
    let archive_path = archive_path.to_path_buf();
    let bin_dir = bin_dir.to_path_buf();
    let ffmpeg_name = ffmpeg_name.to_string();
    let ffprobe_name = ffprobe_name.to_string();

    tokio::task::spawn_blocking(move || {
        let file = std::fs::File::open(&archive_path)
            .map_err(|e| anyhow!("Failed to open archive: {}", e))?;
        let mut archive =
            zip::ZipArchive::new(file).map_err(|e| anyhow!("Failed to open zip: {}", e))?;

        let targets = [ffmpeg_name.as_str(), ffprobe_name.as_str()];

        for i in 0..archive.len() {
            let mut entry = archive
                .by_index(i)
                .map_err(|e| anyhow!("Failed to read zip entry: {}", e))?;

            let name = entry.name().to_string();
            for target in &targets {
                if name.ends_with(target) {
                    let dest = bin_dir.join(format!("{}.new", target));
                    let mut out = std::fs::File::create(&dest)?;
                    std::io::copy(&mut entry, &mut out)?;
                    break;
                }
            }
        }

        Ok::<(), anyhow::Error>(())
    })
    .await
    .map_err(|e| anyhow!("Spawn blocking failed: {}", e))??;

    Ok(())

View on GitHub (pinned to 8600b91f42)