tonhowtf/omniget · error
PowerShell Set-Clipboard failed
Error message
PowerShell Set-Clipboard failed: {} What it means
After copy_file_windows runs the PowerShell Set-Clipboard script, it checks output.status. If the PowerShell process exits non-zero, the captured stderr is surfaced as "PowerShell Set-Clipboard failed: {stderr}". This means the OS-level clipboard write genuinely failed or the script itself errored.
Solutions
- Read the stderr in the error message — it names the actual PowerShell failure (syntax, execution policy, Set-Clipboard availability).
- Run the exact ps_script manually in PowerShell to reproduce and debug the failure.
- For services/CI without an interactive desktop, run in a user session or use a different clipboard API (e.g. arboard/clipboard-win crates).
- Ensure Windows PowerShell 5.0+ (Set-Clipboard exists since PS 5.0); on very old systems use the .NET Windows.Forms Clipboard API in the script.
Example fix
// before
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
return Err(anyhow::anyhow!("PowerShell Set-Clipboard failed: {}", stderr));
}
// after
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
let stdout = String::from_utf8_lossy(&output.stdout);
tracing::error!("[clipboard] PS stdout: {}", stdout);
return Err(anyhow::anyhow!("PowerShell Set-Clipboard failed (exit {:?}): {}", output.status.code(), stderr));
} Defensive patterns
Strategy: try-catch
Validate before calling
// Validate the PowerShell script compiles before running the real copy
let check = std::process::Command::new("powershell")
.args(["-NoProfile", "-NonInteractive", "-Command", "$ErrorActionPreference='Stop'; Set-Clipboard -Value 'test'"])
.output()?;
if !check.status.success() {
eprintln!("PowerShell Set-Clipboard unavailable: {}", String::from_utf8_lossy(&check.stderr));
} Try / catch
match copy_file_to_clipboard(path).await {
Err(e) if e.to_string().contains("PowerShell Set-Clipboard failed") => {
log::error!("PowerShell clipboard error, check stderr in message: {}", e);
// surface stderr details to the user / try alternate clipboard API
}
other => other?,
} Prevention
- Require Windows PowerShell 5.0+ (Set-Clipboard availability)
- Test the ps_script manually before shipping
- Avoid running clipboard code in Session 0 / service contexts
- Log stdout alongside stderr to diagnose script failures
- Consider a native clipboard crate (arboard) instead of shelling out to PowerShell
When it happens
Trigger: powershell -NoProfile -NonInteractive -Command <ps_script> exits with a non-zero status while copying the file to the Windows clipboard — e.g. script parse errors, STA threading issues, or clipboard access being blocked.
Common situations: Windows PowerShell execution policy or Constrained Language Mode blocking the script; clipboard locked by another application; running in a non-interactive service session (Session 0) with no clipboard access; older PowerShell versions lacking Set-Clipboard.
Related errors
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/356d6c7fcaa9b988.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/core/clipboard.rs:166
"No clipboard tool found (tried xclip, xsel, wl-copy)"
))
}
#[cfg(target_os = "windows")]
async fn copy_file_windows(path: &str) -> anyhow::Result<()> {
let ps_script = format!("Set-Clipboard -LiteralPath '{}'", path.replace('\'', "''"));
let output = tokio::task::spawn_blocking(move || {
crate::core::process::std_command("powershell")
.args(["-NoProfile", "-NonInteractive", "-Command", &ps_script])
.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!(
"PowerShell Set-Clipboard failed: {}",
stderr
));
}
tracing::info!("[clipboard] copied file to clipboard (Windows): {}", path);
Ok(())
}
View on GitHub (pinned to 8600b91f42)