{"record":{"id":"48f2fbc3f7df2b8b","repo":"tonhowtf/omniget","slug":"spawn-blocking-failed","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/clipboard.rs","lineNumber":45,"sourceCode":"    #[cfg(target_os = \"windows\")]\n    {\n        copy_file_windows(&path_str).await\n    }\n}\n\n#[cfg(target_os = \"macos\")]\nasync fn copy_file_macos(path: &str) -> anyhow::Result<()> {\n    let path = path.to_string();\n    let output = tokio::task::spawn_blocking(move || {\n        crate::core::process::std_command(\"osascript\")\n            .args([\n                \"-e\",\n                &format!(\"set the clipboard to POSIX file \\\"{}\\\"\", path),\n            ])\n            .output()\n    })\n    .await\n    .map_err(|e| anyhow::anyhow!(\"spawn_blocking failed: {}\", e))??;\n\n    if !output.status.success() {\n        let stderr = String::from_utf8_lossy(&output.stderr);\n        return Err(anyhow::anyhow!(\"osascript failed: {}\", stderr));\n    }\n\n    tracing::info!(\"[clipboard] copied file to clipboard (macOS)\");\n    Ok(())\n}\n\n#[cfg(target_os = \"linux\")]\nasync fn copy_file_linux(path: &str) -> anyhow::Result<()> {\n    let uri = format!(\"file://{}\", path);\n\n    let uri_clone = uri.clone();\n    let xclip_result = tokio::task::spawn_blocking(move || {\n        let mut child = match crate::core::process::std_command(\"xclip\")\n            .args([\"-selection\", \"clipboard\", \"-target\", \"text/uri-list\"])","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/clipboard.rs#L27-L63","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Retry the copy once the runtime is stable; transient shutdown races resolve after init completes.","Ensure copy_file_to_clipboard is awaited within a live tokio runtime (not after runtime shutdown).","Inspect the wrapped JoinError message for a panic; fix the panicking code in the closure."],"exampleFix":"// before\ntokio::runtime::Runtime::new()?.block_on(copy_file_to_clipboard(...)); // dropped too early\n// after\nlet rt = tokio::runtime::Runtime::new()?;\nrt.block_on(copy_file_to_clipboard(...)); // keep rt alive for the call","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match copy_file_to_clipboard(path).await {\n    Err(e) if e.to_string().starts_with(\"spawn_blocking failed\") => {\n        tracing::warn!(\"runtime race during clipboard copy: {e}\");\n        // retry once with a live runtime\n    }\n    other => other?,\n}","preventionTips":["Only call clipboard APIs inside a live tokio runtime","Avoid spawning clipboard copies during app shutdown","Fix panics inside the blocking closure — they surface as this error"],"tags":["macos","async","tokio","clipboard"],"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"}