Repository navigation
Redirecting stderr / the error stream can trigger script-terminating errors #4002
Description
Closely related to #3996 and #11133
The current behavior of calling external programs without stderr redirection is being discussed in the linked issue.
Either way, simply adding 2>$null or 2>&1 - indeed, any redirection of stderr (2>...) - to a command shouldn't fundamentally change its error-handling behavior.
Note that when a host other than the console host is involved (e.g., when in the ISE or when remoting), the difference described below does not occur, but the behavior is fundamentally different (and presumably undesired - see #3996).
Note:
-
Even though the repro steps use external programs, PowerShell commands are equally affected (e.g.,
& { $ErrorActionPreference = 'stop'; Get-Item NosuchFile 2>$null }unexpectedly produces an error, whereas-ErrorAction SilentlyContinuewould not). -
Similarly, using
2>with an actual file as the target is also affected (e.g.,& { $ErrorActionPreference = 'stop'; whoami badarg 2>stderr.txt }aborts, andstderr.txtis empty).
Steps to reproduce
On Unix, replace cmd /c with sh -c.
& { $ErrorActionPreference = 'stop'; cmd /c nosuch; $? }
& { $ErrorActionPreference = 'stop'; cmd /c nosuch 2>$null; $? }Expected behavior
Both commands should fundamentally behave the same, which, based on the current default behavior in the console, is to not report an error, with stderr output passed through in the 1st command and stderr output getting suppressed in the other.
'nosuch' is not recognized as an internal or external command,
operable program or batch file.
False
Actual behavior
- The 1st command behaves as expected.
'nosuch' is not recognized as an internal or external command,
operable program or batch file.
False
- The 2nd command terminates the statement and outputs the first stderr line only in red (note that in Windows PowerShell you get the usual, full error output):
'nosuch' is not recognized as an internal or external command,
The 2nd half of the error message, operable program or batch file., is missing.
Presumably, this happens because:
- as usual, each individual stderr line becomes its own
[System.Management.Automation.ErrorRecord]instance, - and the very 1st line by itself triggers termination of the statement (in this particular case, the
cmderror message happens to span 2 lines).
Note that any 2> redirection causes the symptom, such as 2>&1 or 2>err.txt.
Seemingly, the following happens:
-
Despite redirection of the error stream, the stderr lines are apparently still passing through it, as evidenced by them showing up in
$Errorafterwards. -
With
$ErrorActionPreference = 'stop'in effect, anything getting written to PowerShell's error stream instantly triggers a function/script-terminating error.
Again, note that without a redirection, stderr lines neither show up in $Error nor do they cause the script to be terminated based on $ErrorActionPreference = 'stop'.
Environment data
PowerShell Core v6.0.0-beta.4 on macOS 10.12.5
PowerShell Core v6.0.0-beta.4 on Ubuntu 16.04.2 LTS
PowerShell Core v6.0.0-beta.4 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)
Windows PowerShell v5.1.15063.413 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)
Activity
PaulHigin commentedon Jun 13, 2017
I am able to repro this. This does look like inconsistent behavior. If the default out-putter is configured then the error message is just displayed. But if error is redirected to a pipe then it goes through MshCommandRuntime processing and ErrorActionPreference is effective, and the stop exception is thrown.
This is done here:
https://github.com/PowerShell/PowerShell/blob/master/src/System.Management.Automation/engine/NativeCommandProcessor.cs#L634
BurtHarris commentedon Jun 14, 2017
I disagree w/ expected behavior. I don't think the expected behavior of
2>$nullis documented anywhere. It was an intentional edge-case while I was searching for potential extensions to redirection syntax. You can find other similar cases, e.g.BurtHarris commentedon Jun 14, 2017
P.S. What Michael Klement (@mklement0) is referring to as "the 2nd half of the message" is not "missing", or if so then I found it... It's not coming from the native command, it's a PowerShell ErrorRecord that get's it's own slot.
mklement0 commentedon Jun 14, 2017
Burt Harris (@BurtHarris) I've revised the expected-behavior description in the original post in light of the discussion in the linked issue: if the consensus is that stderr output should never generate an error, then the expected behavior is as now described in the initial post.
Yes, any
2>redirection triggers the symptom, presumably for the reasons Paul Higinbotham (@PaulHigin) states.Without
$ErrorActionPreference = 'Stop'in the mix, you do indeed get all stderr lines recorded in$Error, as an error record each, but with$ErrorActionPreference = 'Stop', the 1st line triggers termination of the pipeline, so the 2nd line never gets recorded in$Error.Indeed, about_Redirection doesn't mention redirecting to
$null, but if it does anything other than silently discarding the stream (as it does with the success stream, for instance), we have a problem - as evidenced by this issue.The unfortunate interaction with
$ErrorActionPreference = 'Stop'is one thing, but the fact that output that you're asking to have suppressed is still getting recorded somewhere - in$Error- is absolutely counter-intuitive.zjrunner commentedon Mar 11, 2019
Where is this issue? I've been able to repro it across an upgrade of a build version and wonder if I'm missing something since this is such an old thread.
repro: powershell v5.1.17763.316, OS 10.0.17763
no-repro: powershell v5.1.16299.967, OS 10.0.16299
Is the upgrade from 16299 to 17763 going to pull this in, and any projection of a fix? We've seen unreliability in our CI builds bailing out at odd times when they hit a machine with this newer powershell installed.
[-]Adding a stderr redirection to an external-utility call changes error handling[/-][+]Redirecting stderr / the error stream to $null can trigger a script-terminating error.[/+][-]Redirecting stderr / the error stream to $null can trigger a script-terminating error.[/-][+]Redirecting stderr / the error stream can trigger script-terminating errors[/+]joaoe commentedon Nov 27, 2019
Hi.
Let me chime in.
I have a script which cheks if a python module is installed
then I enabled strict error handling
$ErrorActionPreference = "stop"and whenever that line runs (and the module is not setup), the whole script aborts instead of running the following steps.I tried also with
python -c ... 2>&1 | out-nulland theNativeCommandErroris always there.This seems like a clear bug to me. If the error stream is being redirected to
$null, that means that the user is explicitly ignoring any errors.So far, the only work around is to use
try{} catch{}.Testcase
andrewducker commentedon Jan 23, 2020
Have just hit this myself. Calling an exe and redirecting the errorstream to a file (it doesn't actually contain an error, just additional info), and had been happily using it for a year or two. I turned ErrorActionPreference to "Stop" globally, and suddenly it fails, despite there not being any actual errors.
joeyaiello commentedon Jul 13, 2020
Related to #3996, want to address similarly
Spell options the same as for helloworlder
SteveL-MSFT commentedon Jul 29, 2020
We discussed this in the @PowerShell/powershell-committee and agreed this is a dupe of #3996
🚀 perf(fsr): add FSR 1.0 upscaling pipeline, bump to 0.2.10
🔖 v0.2.10