tonhowtf/omniget · error

spawn_blocking failed

Error message

spawn_blocking failed: {}

What it means

copy_file_macos runs osascript inside tokio::task::spawn_blocking. If the blocking task itself panics or the runtime is shutting down, the JoinError is wrapped in this 'spawn_blocking failed: {}' error before the osascript result is even examined.

Solutions

  1. Retry the copy once the runtime is stable; transient shutdown races resolve after init completes.
  2. Ensure copy_file_to_clipboard is awaited within a live tokio runtime (not after runtime shutdown).
  3. Inspect the wrapped JoinError message for a panic; fix the panicking code in the closure.

Example fix

// before
tokio::runtime::Runtime::new()?.block_on(copy_file_to_clipboard(...)); // dropped too early
// after
let rt = tokio::runtime::Runtime::new()?;
rt.block_on(copy_file_to_clipboard(...)); // keep rt alive for the call
Defensive patterns

Strategy: try-catch

Try / catch

match copy_file_to_clipboard(path).await {
    Err(e) if e.to_string().starts_with("spawn_blocking failed") => {
        tracing::warn!("runtime race during clipboard copy: {e}");
        // retry once with a live runtime
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling copy_file_to_clipboard on macOS when the spawned blocking task panics (e.g. poisoned state) or the tokio runtime is being dropped during shutdown.

Common situations: App teardown racing a clipboard copy; a panic inside the closure; calling clipboard code from a non-async context where the runtime is already gone.

Related errors


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

Appendix: source

Thrown at src-tauri/omniget-core/src/core/clipboard.rs:45

    #[cfg(target_os = "windows")]
    {
        copy_file_windows(&path_str).await
    }
}

#[cfg(target_os = "macos")]
async fn copy_file_macos(path: &str) -> anyhow::Result<()> {
    let path = path.to_string();
    let output = tokio::task::spawn_blocking(move || {
        crate::core::process::std_command("osascript")
            .args([
                "-e",
                &format!("set the clipboard to POSIX file \"{}\"", path),
            ])
            .output()
    })
    .await
    .map_err(|e| anyhow::anyhow!("spawn_blocking failed: {}", e))??;

    if !output.status.success() {
        let stderr = String::from_utf8_lossy(&output.stderr);
        return Err(anyhow::anyhow!("osascript failed: {}", stderr));
    }

    tracing::info!("[clipboard] copied file to clipboard (macOS)");
    Ok(())
}

#[cfg(target_os = "linux")]
async fn copy_file_linux(path: &str) -> anyhow::Result<()> {
    let uri = format!("file://{}", path);

    let uri_clone = uri.clone();
    let xclip_result = tokio::task::spawn_blocking(move || {
        let mut child = match crate::core::process::std_command("xclip")
            .args(["-selection", "clipboard", "-target", "text/uri-list"])

View on GitHub (pinned to 8600b91f42)