tonhowtf/omniget · error
spawn_blocking failed: {}
Error message
spawn_blocking failed: {} What it means
The downloaded bytes are written to a temp file inside `tokio::task::spawn_blocking`; if the blocking task itself fails (the JoinError case — task panicked or was cancelled), the error is wrapped as "spawn_blocking failed: {e}". Note a plain `std::fs::write` error would surface via the following `??` as an IO error, so this message specifically indicates the blocking task did not complete normally.
Solutions
- Retry the update/download after the runtime is stable — usually transient.
- Ensure the tokio runtime is not being dropped while downloads are in flight (await the update future before shutdown).
- Inspect the wrapped JoinError message for a panic backtrace and fix the panic source if the closure itself is faulty.
- Verify the multi-threaded runtime with blocking pool is used (not a current-thread runtime under heavy load).
- Check disk health — pathological IO failures can surface here via unexpected paths.
Defensive patterns
Strategy: try-catch
Try / catch
match download_ytdlp_binary().await {
Err(e) if e.to_string().contains("spawn_blocking failed") => {
// inspect JoinError (panic/cancel), ensure runtime alive, retry once
}
other => other?,
} Prevention
- Await all background downloads before runtime shutdown.
- Keep panics out of blocking closures; return Result instead.
- Use a multi-threaded tokio runtime with adequate blocking threads.
- Log JoinError details to distinguish panic from cancellation.
When it happens
Trigger: The spawned blocking task panics (e.g. unexpected condition in fs::write path handling) or the tokio runtime is shutting down and cancels the task while writing the temp file during a yt-dlp download/install.
Common situations: App shutdown/runtime teardown racing a background yt-dlp download; a panic inside the closure; runtime built without the blocking-thread pool or with blocking threads exhausted and tasks cancelled.
Related errors
- spawn_blocking failed: {}
- spawn_blocking failed: {}
- tarefa de remoção de fundo falhou: {e}
- Spawn blocking failed: {}
- startup runtime
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/bbb50f7ff5c2e7d3.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/core/ytdlp.rs:1886
// Fail-closed. O yt-dlp publica `SHA2-256SUMS` em toda release; não
// conseguir buscá-lo é indistinguível de alguém suprimindo a verificação,
// então o binário é descartado em vez de instalado sem conferência.
let expected = integrity::expected_from_sums_url(&client, &sums_url, asset)
.await
.map_err(|e| anyhow!("yt-dlp: verificacao de integridade impossivel — {}", e))?;
integrity::verify_sha256(&bytes, &expected, &format!("yt-dlp ({:?})", channel))?;
let temp = target.with_file_name(format!(
"{}.new",
target
.file_name()
.and_then(|n| n.to_str())
.unwrap_or("yt-dlp")
));
let temp_clone = temp.clone();
tokio::task::spawn_blocking(move || std::fs::write(&temp_clone, &bytes))
.await
.map_err(|e| anyhow!("spawn_blocking failed: {}", e))??;
crate::core::dependencies::replace_managed_binary(&temp, &target)?;
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let perms = std::fs::Permissions::from_mode(0o755);
std::fs::set_permissions(&target, perms)?;
}
#[cfg(target_os = "macos")]
{
let target_mac = target.clone();
let _ = tokio::task::spawn_blocking(move || {
crate::core::process::std_command("xattr")
.args(["-d", "com.apple.quarantine"])
.arg(&target_mac)
.output()View on GitHub (pinned to 8600b91f42)