cjpais/Handy · error

get_available_accelerators panicked

Error message

get_available_accelerators panicked

What it means

Panic when the spawn_blocking task running get_available_accelerators itself panics: awaiting the JoinHandle yields a JoinError with is_panic(), which this .expect converts into an abort of the awaiting task. The wrapped function enumerates ORT accelerators (transcribe-rs) and transcribe-cpp GPU devices, which loads Metal/Vulkan dynamic libraries and probes hardware — a panic inside those native layers bubbles out here.

Solutions

  1. Validate the graphics stack first: on Linux run vulkininfo/vulkaninfo and fix ICD/driver errors it reports; on other platforms update GPU drivers
  2. Select the CPU accelerator in settings so GPU paths are not exercised (if enumeration still runs, keep the app but report the crash with logs)
  3. Replace .expect with JoinError logging (downcast the panic payload) to capture the real panic message and backtrace
  4. If it started after a dependency bump, pin/rollback the transcribe-cpp or transcribe-rs version

Example fix

// before
tauri::async_runtime::spawn_blocking(crate::managers::transcription::get_available_accelerators)
    .await
    .expect("get_available_accelerators panicked")

// after — degrade to a CPU-only answer instead of aborting the command
match tauri::async_runtime::spawn_blocking(
    crate::managers::transcription::get_available_accelerators,
)
.await
{
    Ok(accels) => accels,
    Err(e) => {
        log::error!("accelerator enumeration failed: {e}");
        crate::managers::transcription::AvailableAccelerators::cpu_only()
    }
}
Defensive patterns

Strategy: try-catch

Try / catch

match tauri::async_runtime::spawn_blocking(
    crate::managers::transcription::get_available_accelerators,
)
.await
{
    Ok(accels) => accels,
    Err(join_err) => {
        log::error!("accelerator enumeration panicked: {join_err}");
        // degrade: report CPU-only so the settings UI still works
        cpu_only_accelerators()
    }
}

Prevention

When it happens

Trigger: Invoking the get_available_accelerators Tauri command (settings UI or the lib.rs startup pre-warm) while native enumeration panics — typically a broken Vulkan ICD/loader or driver mismatch on Linux, or Metal problems on non-standard macOS setups. The panic payload is lost unless you inspect the JoinError.

Common situations: Broken or mismatched GPU drivers after an OS update; stale Vulkan loader with bad ICD configs; VMs or translation layers without a real GPU; a transcribe-cpp version regression that panics during device enumeration.

Related errors


AI-assisted analysis of cjpais/Handy@fbd4e15fa1 (2026-08-17). Data as JSON: /api/errors/dfff375ec432f65f. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/src/shortcut/mod.rs:1404

pub fn change_transcribe_gpu_device(app: AppHandle, device: Option<String>) -> Result<(), String> {
    let mut s = settings::get_settings(&app);
    s.transcribe_gpu_device = device;
    save_accelerator_and_reload_next_use(&app, s);
    Ok(())
}

/// Return which accelerators and GPU devices are available for this build.
///
/// First-call cost is dominated by enumerating GPU devices through the
/// transcribe.cpp Metal/Vulkan backend, which loads dynamic libraries and
/// probes hardware. Run it on the blocking pool so the webview thread
/// stays responsive — see also the startup pre-warm in `lib.rs`.
#[tauri::command]
#[specta::specta]
pub async fn get_available_accelerators() -> crate::managers::transcription::AvailableAccelerators {
    tauri::async_runtime::spawn_blocking(crate::managers::transcription::get_available_accelerators)
        .await
        .expect("get_available_accelerators panicked")
}

View on GitHub (pinned to fbd4e15fa1)