You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Suppressing stderr output with 2>$null or redirecting it to a file causes stderr lines to be recorded in $Error #11133
Stderr output doesn't belong in PowerShell's error stream, because it cannot be assumed to represent errors - that's why it prints straight to the host by default.
Using 2>$null should mean: discard stderr output. That it would then show up in $Error is certainly not the intent.
Michael Klement (@mklement0) Logically standard error output belongs in PowerShell's output stream because because that's where executables write their errors. Unfortunately over the years more and more *NIX binaries use stderr for a bunch of things that have nothing to do with errors. This is annoying and unfortunate. PowerShell's output stream is strongly typed so whatever gets written into it has to get wrapped in an ErrorRecord unlike the subprocess pipe which is just an undifferentiated stream of bytes so you get very different behavior. (Wrapping the output into an error object is also important because that's how Out-Default demultiples the merged output stream.)
That it would then show up in $Error is certainly not the intent.
It most certainly is the intent, specifically $error is intended to be an in-memory log of all the errors that occur during execution, suppressed or not. It's purpose, like any error log, is to allow forensic analysis of the execution.
That stderr output goes through the error stream with redirection 2> is also highly problematic
I didn't understand this statement. WRT the linked issue, errors are either exceptions (terminating errors) or something written to the error stream (non-terminating errors.) -ErrorAction Stop changes a non-terminating error into a terminating error. Thus error action only applies to things being written to the error stream.. Consequently, if you redirect the error stream to the output stream, the error action preference no longer has any effect.
Unfortunately over the years more and more *NIX binaries use stderr for a bunch of things that have nothing to do with errors. This is annoying and unfortunate.
The root problem is that native programs only have 2 output streams at their disposal: stdout and stderr.
This is an unfortunate limitation, which PowerShell - commendably - has overcome in its own realm.
Given this limitation, native programs have no choice but to write anything that isn't data to stderr, lest they pollute the data output stream (stdout).
It is a longstanding practice that is the best approach within the confines of the stated limitation.
Because the presence of stderr output can therefore not be assumed to represent error conditions, PowerShell's console host's default behavior is the right approach:
print stderr lines to the host
do not record stderr lines in $Error
If needed, stderr output can be targeted selectively with a 2> redirection; currently, aside from 2>$null discussed below, you can only redirect to a file; it would be nice to have an analog to -ErrorVariable for capturing stderr lines in a variable, which is what #4332 proposes.
It most certainly is the intent, specifically $error is intended to be an in-memory log of all the errors that occur during execution, suppressed or not.
As explained above, for good reasons that doesn't apply to stderr output, which is passed through to the host.
That it would suddenly apply when you use 2>$null to explicitly signal the intent to discard stderr can't be anyone's intent, least of all the user's.
Thus error action only applies to things being written to the error stream..
Not only should 2>$null not touch the error stream at all, that a redirection designed to discard the stream's output, would - situationally, based on $ErrorActionPreference - trigger aborting execution as if it were writing to the error stream is obviously the opposite of the user's intent.
Even with true error stream output from PowerShell commands 2>$null is currently broken:
Like -ErrorAction SilentlyContinue it still records the error in $Error (which I think is problematic - see below).
Unlike -ErrorAction SilentlyContinue (or -ErrorAction Ignore), it unexpectedly throws a runspace-terminating error when $ErrorActionPreference = 'Stop' happens to be in effect:
$ErrorActionPreference='Stop'# OK: No error output, but $Error is still populated.Get-Item/NoSuch -ErrorAction SilentlyContinue
# Kaboom! A runspace-terminating error occurs.Get-Item/NoSuch 2>$null
Even if 2>$null were made fully equivalent to -ErrorAction SilentlyContinue, it seems like the wrong way to go.
The syntax 2>$null clearly suggests the intent to discard the error stream's output (as its native cousins 2>/dev/null and 2>NUL do), and should therefore be the equivalent of -ErrorAction Ignore.
changed the title [-]Suppressing stderr output with 2>$null causes stderr lines to be recorded in $Error[/-][+]Suppressing stderr output with 2>$null or redirecting it to a file causes stderr lines to be recorded in $Error[/+]on Feb 7, 2020
Activity
iSazonov commentedon Nov 20, 2019
I think it is expected as -ErrorAction SilentlyContinue behavior.
mklement0 commentedon Nov 20, 2019
Ilya (@iSazonov):
Stderr output doesn't belong in PowerShell's error stream, because it cannot be assumed to represent errors - that's why it prints straight to the host by default.
Using
2>$nullshould mean: discard stderr output. That it would then show up in$Erroris certainly not the intent.That stderr output goes through the error stream with redirection
2>is also highly problematic with respect to suddenly being subject to$ErrorActionPreference = 'Stop'- see Redirecting stderr / the error stream can trigger script-terminating errors #4002.Providing an easy way to collect stderr lines is the subject of #4332.
BrucePay commentedon Nov 21, 2019
Michael Klement (@mklement0) Logically standard error output belongs in PowerShell's output stream because because that's where executables write their errors. Unfortunately over the years more and more *NIX binaries use stderr for a bunch of things that have nothing to do with errors. This is annoying and unfortunate. PowerShell's output stream is strongly typed so whatever gets written into it has to get wrapped in an
ErrorRecordunlike the subprocess pipe which is just an undifferentiated stream of bytes so you get very different behavior. (Wrapping the output into an error object is also important because that's howOut-Defaultdemultiples the merged output stream.)It most certainly is the intent, specifically $error is intended to be an in-memory log of all the errors that occur during execution, suppressed or not. It's purpose, like any error log, is to allow forensic analysis of the execution.
I didn't understand this statement. WRT the linked issue, errors are either exceptions (terminating errors) or something written to the error stream (non-terminating errors.)
-ErrorAction Stopchanges a non-terminating error into a terminating error. Thus error action only applies to things being written to the error stream.. Consequently, if you redirect the error stream to the output stream, the error action preference no longer has any effect.mklement0 commentedon Nov 22, 2019
Bruce Payette (@BrucePay):
The root problem is that native programs only have 2 output streams at their disposal: stdout and stderr.
This is an unfortunate limitation, which PowerShell - commendably - has overcome in its own realm.
Given this limitation, native programs have no choice but to write anything that isn't data to stderr, lest they pollute the data output stream (stdout).
It is a longstanding practice that is the best approach within the confines of the stated limitation.
Because the presence of stderr output can therefore not be assumed to represent error conditions, PowerShell's console host's default behavior is the right approach:
$ErrorIf needed, stderr output can be targeted selectively with a
2>redirection; currently, aside from2>$nulldiscussed below, you can only redirect to a file; it would be nice to have an analog to-ErrorVariablefor capturing stderr lines in a variable, which is what #4332 proposes.As explained above, for good reasons that doesn't apply to stderr output, which is passed through to the host.
That it would suddenly apply when you use
2>$nullto explicitly signal the intent to discard stderr can't be anyone's intent, least of all the user's.Not only should
2>$nullnot touch the error stream at all, that a redirection designed to discard the stream's output, would - situationally, based on$ErrorActionPreference- trigger aborting execution as if it were writing to the error stream is obviously the opposite of the user's intent.Even with true error stream output from PowerShell commands
2>$nullis currently broken:Like
-ErrorAction SilentlyContinueit still records the error in$Error(which I think is problematic - see below).Unlike
-ErrorAction SilentlyContinue(or-ErrorAction Ignore), it unexpectedly throws a runspace-terminating error when$ErrorActionPreference = 'Stop'happens to be in effect:Even if
2>$nullwere made fully equivalent to-ErrorAction SilentlyContinue, it seems like the wrong way to go.The syntax
2>$nullclearly suggests the intent to discard the error stream's output (as its native cousins2>/dev/nulland2>NULdo), and should therefore be the equivalent of-ErrorAction Ignore.[-]Suppressing stderr output with 2>$null causes stderr lines to be recorded in $Error[/-][+]Suppressing stderr output with 2>$null or redirecting it to a file causes stderr lines to be recorded in $Error[/+]mklement0 commentedon Aug 2, 2020
Closed in favor of #3996 (comment)