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

  1. Retry the update/download after the runtime is stable — usually transient.
  2. Ensure the tokio runtime is not being dropped while downloads are in flight (await the update future before shutdown).
  3. Inspect the wrapped JoinError message for a panic backtrace and fix the panic source if the closure itself is faulty.
  4. Verify the multi-threaded runtime with blocking pool is used (not a current-thread runtime under heavy load).
  5. 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

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


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)