{"record":{"id":"907f2cc223fb92c0","repo":"tonhowtf/omniget","slug":"spawn-blocking-failed-whisper","errorCode":null,"errorMessage":"Spawn blocking failed: {}","messagePattern":"Spawn blocking failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/whisper.rs","lineNumber":221,"sourceCode":"        models: list_models(),\n        models_dir: models_dir().map(|d| d.to_string_lossy().to_string()),\n    }\n}\n\npub async fn install(variant: &str, progress: ProgressFn) -> anyhow::Result<PathBuf> {\n    let name = asset_name(variant)?;\n    let dir = managed_dir().ok_or_else(|| anyhow!(\"Could not determine data directory\"))?;\n    let client = github::client()?;\n    let asset = github::asset(&client, REPO, None, |n| n == name).await?;\n    tracing::info!(\"[whisper] baixando {} ({})\", asset.name, asset.tag);\n    let data = github::download(&client, &asset, false, &progress, \"whisper-cli\").await?;\n    let staging = dir.with_extension(\"new\");\n    let _ = std::fs::remove_dir_all(&staging);\n    let staging_c = staging.clone();\n    let asset_name_c = asset.name.clone();\n    tokio::task::spawn_blocking(move || github::unpack(&data, &asset_name_c, &staging_c))\n        .await\n        .map_err(|e| anyhow!(\"Spawn blocking failed: {}\", e))??;\n    let Some(exe) = github::find_file(&staging, &bin_name(\"whisper-cli\")) else {\n        let _ = std::fs::remove_dir_all(&staging);\n        return Err(anyhow!(\"o pacote baixado nao contem o whisper-cli\"));\n    };\n    github::make_executable(&exe);\n    // As libs (.dll/.so) ficam ao lado do executável no mesmo pacote.\n    github::swap_dir(&staging, &dir)?;\n    github::strip_quarantine(&dir).await;\n    let final_exe = github::find_file(&dir, &bin_name(\"whisper-cli\"))\n        .ok_or_else(|| anyhow!(\"whisper-cli sumiu depois de mover a pasta\"))?;\n    std::fs::write(dir.join(\"VERSION\"), &asset.tag).ok();\n    Ok(final_exe)\n}\n\n#[derive(Debug, Clone, Deserialize)]\npub struct TranscribeOptions {\n    pub input: String,\n    pub model: String,","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/whisper.rs#L203-L239","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the runtime logs for the panic message inside the JoinError and fix the underlying panic cause in unpack.","Re-run the install; verify the downloaded archive is complete (re-download).","Keep the tokio runtime alive until background installs finish (e.g. await a JoinHandle before shutdown).","If panics are expected for bad archives, change unpack to return Result instead of panicking."],"exampleFix":"// before\ntokio::task::spawn_blocking(move || github::unpack(&data, &name, &staging))\n    .await\n    .map_err(|e| anyhow!(\"Spawn blocking failed: {}\", e))??;\n\n// after — avoid panics inside the blocking task by returning Result\ntokio::task::spawn_blocking(move || github::unpack(&data, &name, &staging))\n    .await\n    .map_err(|e| anyhow!(\"unpack task panicked or was cancelled: {}\", e))??;","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match whisper::install(variant, &progress).await {\n    Err(e) if e.to_string().starts_with(\"Spawn blocking failed\") => {\n        // inspect runtime logs for the panic in github::unpack, then retry once\n    }\n    other => other?,\n}","preventionTips":["Keep the tokio runtime alive until background installs complete.","Re-download if the archive may be corrupt.","Prefer Result-returning helpers over panicking code in blocking tasks."],"tags":["tokio","spawn-blocking","panic","unpack"],"backgroundTag":"thread-interrupted","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}