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
- Check application logs for a panic inside the spawn_blocking closure at the same timestamp
- Ensure the tokio runtime is alive for the duration of the download (don't drop/shutdown mid-await)
- Retry the download; the error is usually transient if caused by shutdown
- 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
- Keep the tokio runtime alive for the whole install flow
- Avoid panicking code paths inside the spawn_blocking closure
- Don't trigger installs during app shutdown
- Add a retry around transient JoinError cases
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
- spawn_blocking failed
- Spawn blocking failed
- worker task panicked
- tarefa de remoção de fundo falhou
- spawn_blocking failed
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)