tonhowtf/omniget · error · anyhow::Error

spawn_blocking failed

Error message

spawn_blocking failed: {}

What it means

The blocking file-write of the downloaded FFmpeg archive is offloaded via tokio::task::spawn_blocking. If the JoinHandle resolves to a JoinError — the blocking task panicked (e.g. I/O thread panic) or the runtime is shutting down — this anyhow error wraps it. Note the extra ? after map_err propagates the inner std::io::Error separately.

Solutions

  1. Check application logs for a panic inside the spawn_blocking closure at the same timestamp
  2. Ensure the tokio runtime is alive for the duration of the download (don't drop/shutdown mid-await)
  3. Retry the download; the error is usually transient if caused by shutdown
  4. Avoid calling ensure_ffmpeg/update_ffmpeg during app teardown
Defensive patterns

Strategy: try-catch

Try / catch

match download_ffmpeg().await {
    Ok(p) => ...,
    Err(e) if e.to_string().contains("spawn_blocking failed") => {
        eprintln!("blocking task panicked or runtime shutdown: {e}");
    }
    Err(e) => ...,
}

Prevention

When it happens

Trigger: The closure moved into spawn_blocking panics (unwinding inside std::fs::write path handling) or the tokio runtime is being dropped while the blocking task is queued/running.

Common situations: Application shutdown mid-download; a panic in the blocking worker (rare, e.g. path issues); calling download_ffmpeg outside a live tokio runtime context.

Related errors


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

Appendix: source

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

    for (url, archive_type) in downloads {
        tracing::info!("Downloading FFmpeg component from {}", url);
        let response = client.get(url).send().await?;
        if !response.status().is_success() {
            return Err(anyhow!(
                "Failed to download FFmpeg from {}: HTTP {}",
                url,
                response.status()
            ));
        }

        let temp_path = bin_dir.join(".ffmpeg_download.tmp");
        let bytes = response.bytes().await?;
        let data = bytes.to_vec();
        let temp_clone = temp_path.clone();
        tokio::task::spawn_blocking(move || std::fs::write(&temp_clone, &data))
            .await
            .map_err(|e| anyhow!("spawn_blocking failed: {}", e))??;

        let file_size = std::fs::metadata(&temp_path)?.len();
        if file_size < 1_000_000 {
            let _ = std::fs::remove_file(&temp_path);
            return Err(anyhow!(
                "Downloaded file from {} is too small ({}B) — likely an error page",
                url,
                file_size
            ));
        }

        match archive_type {
            ArchiveType::Zip => {
                extract_zip_ffmpeg(&temp_path, &bin_dir, &ffmpeg_name, &ffprobe_name).await?
            }
            ArchiveType::TarXz => {
                extract_tar_xz_ffmpeg(&temp_path, &bin_dir, &ffmpeg_name, &ffprobe_name).await?
            }

View on GitHub (pinned to 8600b91f42)