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

  1. Read the stderr in the error message — it names the actual PowerShell failure (syntax, execution policy, Set-Clipboard availability).
  2. Run the exact ps_script manually in PowerShell to reproduce and debug the failure.
  3. For services/CI without an interactive desktop, run in a user session or use a different clipboard API (e.g. arboard/clipboard-win crates).
  4. 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

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)