tonhowtf/omniget · error · anyhow::Error

spawn_blocking failed

Error message

spawn_blocking failed: {}

What it means

The archive extraction runs off the async runtime via tokio::task::spawn_blocking. If the blocking task itself panics (or the runtime is shutting down), the JoinHandle resolves to a JoinError and this error wraps it. Note the double `??`: this error covers the join failure, while extraction I/O errors surface separately with their own messages.

Solutions

  1. Read the wrapped panic message from the error chain to find the panicking operation in extract_pdfium_archive
  2. Test extraction against the exact downloaded archive to reproduce the panic
  3. Replace panicking unwraps/expects in extract_pdfium_archive with proper anyhow errors
  4. Retry the installation when the cause was runtime shutdown during app exit

Example fix

// before
let name = entry.mangled_name().unwrap();
// after
let name = entry.mangled_name()
    .map_err(|e| anyhow!("bad archive entry name: {}", e))?;
Defensive patterns

Strategy: try-catch

Validate before calling

// validate the archive before extraction
let cursor = std::io::Cursor::new(&bytes);
let mut zip = zip::ZipArchive::new(cursor)?; // Err here = corrupt archive
zip.by_index(0)?;

Try / catch

match ensure_pdfium().await {
    Err(e) if e.to_string().contains("spawn_blocking failed") => {
        // blocking task panicked; inspect the wrapped panic text and re-download
    }
    other => other.map(|_| ()),
}

Prevention

When it happens

Trigger: extract_pdfium_archive panics inside the blocking thread (e.g. unwrap on bad zip entry, OOM during decompression) or the tokio runtime is being dropped while the task runs.

Common situations: Corrupt or maliciously crafted archive triggering a panic in the zip decoder; app shutdown cancelling in-flight installation; runtime built without blocking-thread budget.

Related errors


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

Appendix: source

Thrown at src-tauri/omniget-core/src/core/pdfium.rs:202

        ));
    }
    let bytes = response.bytes().await?.to_vec();
    if bytes.len() < 100_000 {
        return Err(anyhow!(
            "Downloaded pdfium archive is too small ({} bytes) — likely an error page",
            bytes.len()
        ));
    }

    let target_path_clone = target_path.clone();
    let target_dir_clone = target_dir.clone();
    let lib_name = lib_filename.to_string();
    let extracted_version =
        tokio::task::spawn_blocking(move || -> anyhow::Result<Option<String>> {
            extract_pdfium_archive(&bytes, &target_path_clone, &target_dir_clone, &lib_name)
        })
        .await
        .map_err(|e| anyhow!("spawn_blocking failed: {}", e))??;

    if let Some(version_marker) = pdfium_version_marker_path() {
        let base = extracted_version.unwrap_or_else(|| "latest".to_string());
        let value = format!("{} ({})", base, archive_name);
        let _ = std::fs::write(&version_marker, value);
    }

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

View on GitHub (pinned to 8600b91f42)