type: rule
status: active
timestamp: 2026-06-27
tags: [powershell, stderr, automation, hard-rule]

PowerShell: native commands writing to stderr trip strict mode

Cargo/winget/npm/gcc print to stderr. PS 5.1 + EAP=Stop wraps stderr in RemoteException. Pipe through cmd /c ... 2>&1

PowerShell: native commands + stderr = silent abort

Why this rule exists

cargo install --git ... prints Updating git repository ... to STDERR as progress info, not an error. PowerShell with $ErrorActionPreference = 'Stop' treats every stderr line as a RemoteException and aborts the script. Same problem with winget, npm install, gcc, apt, pip.

Observed 2026-06-27 in install-speed-stack.ps1 line 61: cargo.exe : Updating git repository https://github.com/rtk-ai/rtk“ ? NativeCommandError ? script died mid-RTK-build despite the build actually succeeding (it had compiled to 100%).

Rule

When invoking ANY native command that prints progress or info to stderr:

  1. Pipe through cmd /c "<cmd> 2>&1" to merge streams BEFORE PS sees them.
  2. Locally set $ErrorActionPreference = 'Continue' around the call:
$prev = $ErrorActionPreference
$ErrorActionPreference = 'Continue'
try {
  & cmd /c "cargo install --locked rtk 2>&1" | Out-Host
  $rc = $LASTEXITCODE
} finally {
  $ErrorActionPreference = $prev
}
if ($rc -ne 0) { throw "...real failure..." }

Or use the Invoke-Native helper in install-agents.ps1 that wraps this.

Anti-patterns

When the stderr is actually an error

Check $LASTEXITCODE after the call. That’s the only reliable signal for native commands; stream content is not.

Cross-refs


Edit on GitHub · Back to index