tonhowtf/omniget · error · anyhow::Error

Deno binary not found after extraction

Error message

Deno binary not found after extraction

What it means

Raised in download_deno after the zip extraction completes: deno_target (bin_dir/deno_name) does not exist on disk. The zip was processed but no entry matched the expected deno binary name (name ends with deno_name, or is exactly "deno"/"deno.exe"), so nothing was written to the target path.

Solutions

  1. Log the zip entry names and compare with deno_name; loosen the match if the layout changed
  2. Pin Deno to a version whose zip layout is known to work
  3. Verify the correct platform-specific deno zip URL was downloaded
  4. Ensure bin_dir exists and extraction wrote files (check create_dir_all and permissions)

Example fix

// before
if name.ends_with(&deno_name_clone) || name == "deno" || name == "deno.exe" {
// after
let base = name.rsplit('/').next().unwrap_or(&name);
if base == deno_name_clone || base == "deno" || base == "deno.exe" {
Defensive patterns

Strategy: validation

Validate before calling

// verify the expected binary exists after extraction, with a diagnostic
if !deno_target.exists() {
    let entries: Vec<String> = archive
        .file_names()
        .unwrap_or_default()
        .to_vec();
    return Err(anyhow!(
        "Deno binary not found after extraction; zip contained: {:?}",
        entries
    ));
}

Type guard

fn deno_binary_present(bin_dir: &std::path::Path, deno_name: &str) -> bool {
    bin_dir.join(deno_name).is_file()
}

Try / catch

match std::fs::metadata(&deno_target) {
    Ok(m) if m.is_file() && m.len() > 0 => { /* proceed to chmod */ }
    _ => return Err(anyhow!(
        "Deno binary missing after extraction; check zip layout for {}",
        deno_name
    )),
}

Prevention

When it happens

Trigger: The downloaded Deno zip contains no entry matching the expected binary name for the current platform, or entry matching failed, leaving bin_dir/deno_name absent after extraction.

Common situations: Deno changed the archive layout in a new release; wrong deno_name computed for the target OS/arch; the match condition (ends_with deno_name, == "deno", == "deno.exe") misses entries inside a subdirectory with a different casing; the extraction silently skipped all entries.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

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

                .map_err(|e| anyhow!("Failed to read zip entry: {}", e))?;

            let name = file.name().to_string();
            if name.ends_with(&deno_name_clone) || name == "deno" || name == "deno.exe" {
                let dest = bin_dir_clone.join(&deno_name_clone);
                let mut buf = Vec::new();
                std::io::Read::read_to_end(&mut file, &mut buf)?;
                std::fs::write(&dest, &buf)?;
                break;
            }
        }

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

    if !deno_target.exists() {
        return Err(anyhow!("Deno binary not found after extraction"));
    }

    #[cfg(unix)]
    {
        use std::os::unix::fs::PermissionsExt;
        let _ = std::fs::set_permissions(&deno_target, std::fs::Permissions::from_mode(0o755));
    }

    #[cfg(target_os = "macos")]
    {
        let deno_mac = deno_target.clone();
        let _ = tokio::task::spawn_blocking(move || {
            crate::core::process::std_command("xattr")
                .args(["-d", "com.apple.quarantine"])
                .arg(&deno_mac)
                .output()
        })
        .await;

View on GitHub (pinned to 8600b91f42)