tonhowtf/omniget · error

Spawn blocking failed

Error message

Spawn blocking failed: {}

What it means

install() unpacks the downloaded release archive inside tokio::task::spawn_blocking. If the blocking task itself panics or is cancelled, the JoinHandle yields a JoinError, which is wrapped as "Spawn blocking failed: {e}". Note the `??`: this error is about the task failing to complete, not about unpack() returning Err (that propagates unchanged).

Solutions

  1. Check the runtime logs for the panic message inside the JoinError and fix the underlying panic cause in unpack.
  2. Re-run the install; verify the downloaded archive is complete (re-download).
  3. Keep the tokio runtime alive until background installs finish (e.g. await a JoinHandle before shutdown).
  4. If panics are expected for bad archives, change unpack to return Result instead of panicking.

Example fix

// before
tokio::task::spawn_blocking(move || github::unpack(&data, &name, &staging))
    .await
    .map_err(|e| anyhow!("Spawn blocking failed: {}", e))??;

// after — avoid panics inside the blocking task by returning Result
tokio::task::spawn_blocking(move || github::unpack(&data, &name, &staging))
    .await
    .map_err(|e| anyhow!("unpack task panicked or was cancelled: {}", e))??;
Defensive patterns

Strategy: try-catch

Try / catch

match whisper::install(variant, &progress).await {
    Err(e) if e.to_string().starts_with("Spawn blocking failed") => {
        // inspect runtime logs for the panic in github::unpack, then retry once
    }
    other => other?,
}

Prevention

When it happens

Trigger: The spawned github::unpack closure panics (e.g. internal unwrap on a malformed archive) or the runtime shuts down/cancels the task while install() is awaiting it.

Common situations: Corrupt or truncated download tripping a panic inside unpack; dropping the tokio runtime while a large archive is still being extracted; task aborts during app shutdown mid-install.

Related errors


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

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/whisper.rs:221

        models: list_models(),
        models_dir: models_dir().map(|d| d.to_string_lossy().to_string()),
    }
}

pub async fn install(variant: &str, progress: ProgressFn) -> anyhow::Result<PathBuf> {
    let name = asset_name(variant)?;
    let dir = managed_dir().ok_or_else(|| anyhow!("Could not determine data directory"))?;
    let client = github::client()?;
    let asset = github::asset(&client, REPO, None, |n| n == name).await?;
    tracing::info!("[whisper] baixando {} ({})", asset.name, asset.tag);
    let data = github::download(&client, &asset, false, &progress, "whisper-cli").await?;
    let staging = dir.with_extension("new");
    let _ = std::fs::remove_dir_all(&staging);
    let staging_c = staging.clone();
    let asset_name_c = asset.name.clone();
    tokio::task::spawn_blocking(move || github::unpack(&data, &asset_name_c, &staging_c))
        .await
        .map_err(|e| anyhow!("Spawn blocking failed: {}", e))??;
    let Some(exe) = github::find_file(&staging, &bin_name("whisper-cli")) else {
        let _ = std::fs::remove_dir_all(&staging);
        return Err(anyhow!("o pacote baixado nao contem o whisper-cli"));
    };
    github::make_executable(&exe);
    // As libs (.dll/.so) ficam ao lado do executável no mesmo pacote.
    github::swap_dir(&staging, &dir)?;
    github::strip_quarantine(&dir).await;
    let final_exe = github::find_file(&dir, &bin_name("whisper-cli"))
        .ok_or_else(|| anyhow!("whisper-cli sumiu depois de mover a pasta"))?;
    std::fs::write(dir.join("VERSION"), &asset.tag).ok();
    Ok(final_exe)
}

#[derive(Debug, Clone, Deserialize)]
pub struct TranscribeOptions {
    pub input: String,
    pub model: String,

View on GitHub (pinned to 8600b91f42)