question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Cmdlet.ThrowTerminatingError() is not affected by `-ErrorAction`

See original GitHub issue

If a cmdlet uses ThrowTerminatingError() then that ErrorRecord is not affected by the common -ErrorAction parameter. However, it is affected by $ErrorActionPreference. This inconsistency is not a regression from Windows PowerShell 5.1, but is a cause of lots of user confusion. Note that -ErrorAction Break DOES work because the code explicitly checks for that, but other values are not checked.

Steps to reproduce

Invoke-WebRequest https://foo.lskdjf -ErrorAction ignore

Expected behavior

Nothing

Actual behavior

Error printed

Environment data

Name                           Value
----                           -----
PSVersion                      7.2.0-preview.3
PSEdition                      Core
GitCommitId                    7.2.0-preview.3
OS                             Darwin 20.3.0 Darwin Kernel Version 20.3.0: Thu Jan 21 00:07:06 PST 2021; root:xnu-7195.81.3~1/RELEASE_X86_64
Platform                       Unix
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:1
  • Comments:17 (11 by maintainers)

github_iconTop GitHub Comments

2reactions
SeeminglySciencecommented, Feb 25, 2021
  • thread-terminating is technically clearer

The full phrase “the current thread of execution” is unfortunately sorta needed there as it doesn’t actually terminate the thread (in 99.99% of cases). It’s difficult to come up with good terminology for this. Maybe “call stack terminating”? That’s going to be mostly meaningless to a lot of folks probably.

1reaction
jhoneillcommented, Apr 15, 2023

Following discussions in #19500 there’s a clarification / pedantic point to add. That issue concerns something different - if the current $errorActionPreference in a function, set by -ErrorAction or inherited from the caller, is silently continue throw is considered to be caught and handled silently, and execution continues. But it also strayed into -ErrorAction working / not working and ErrorActionPreference.

I think the initial post mis-explains the behaviour

consider this code

function foo {
[CmdletBinding()]
Param( $p)
$ErrorActionPreference ="SilentlyContinue"
if ($P -gt 1) {
    $err_rec = [System.Management.Automation.ErrorRecord]::new("Oops","",7,$null) 
    $PSCmdlet.ThrowTerminatingError($err_rec)
}
"Something bad happens if $p >1 "
}

It sets $ErrorActionPreference - so, according to the initial description, we would expect the error to be supressed but in practice:

> foo 2
foo: Oops

Whatever this error is returned to does what $errorActionPreference says it should do. So if the function is called from a second function:

function bar {
[CmdletBinding()]
Param( $p)
$ErrorActionPreference
foo $p
"returned to bar"
}

Execution continues back in the calling function after printing the error if the preference is continue.

 bar 2
Continue
foo: 
Line |
  19 |  foo $p
     |  ~~~~~~
     | Oops
returned to bar

Execution continues back in the calling function WITHOUT printing the error if the preference is SILENTLYcontinue.

bar 2 -ErrorAction SilentlyContinue
SilentlyContinue
returned to bar

And it stops without printing “returned to bar” if the preference is STOP.

As already pointed out by @mklement0 et al. “terminating” errors have multiple varieties

If I change the first function to use throw the message “returned to bar” isn’t printed

function foo {
[CmdletBinding()]
Param( $p)
if ($P -gt 1) {
    $err_rec = [System.Management.Automation.ErrorRecord]::new("Oops","",7,$null) 
    throw $err_rec
}
"Something bad happens if $p >1 "
}
bar 2 
Continue
InvalidOperation: 
Line |
   6 |      throw $err_rec
     |      ~~~~~~~~~~~~~~
     | Oops

but if the error-action-preference is silentlycontinue the throw is caught immediately.

bar 2 -errorAction SilentlyContinue
SilentlyContinue
Something bad happens if 2 >1
returned to bar

This creates problems for people writing and calling functions. For writers calling $pscmdlet.ThrowTerminatingError() side steps -ErrorAction (think of that as “do X when an error is thrown to you” and the ThrowTerminatingError as “throw an error to your caller”) , and throw stops other code running in the calling script - so without try{} Catch{} any clean up is missed.
For callers -ErrorAction silently continue works for some errors, but for a throw it can cause the function code to continue and do something harmful (e.g. in
$x = get-thingName; if (-not $x) {throw} ; delete-thing -name "$x*" -errorAction SilentlyContinue would delete every thing) .

Read more comments on GitHub >

github_iconTop Results From Across the Web

PowerShell ThrowTerminatingError() errors are not true ...
Note that -ErrorAction Stop does not help, it is not designed for such errors. It affects non-terminating errors ( WriteError() , Write-Error )....
Read more >
Everything you wanted to know about exceptions
ThrowTerminatingError() is that it creates a terminating error within your Cmdlet but it turns into a non-terminating error after it leaves your ...
Read more >
Can someone please explain this seemingly inconsistent ...
ThrowTerminatingError() API in cmdlets. They behave somewhat like a script-terminating error, but they will only stop the current pipeline ...
Read more >
Read The Big Book of PowerShell Error Handling
NET method that throws an exception, a Cmdlet or Advanced Function that produce non-terminating errors when ErrorAction is set to Stop, and an...
Read more >
Analysis of Error Handling Test Results
The final section tests how PowerShell behaves when it encounters unhandled terminating errors from each possible source (a Cmdlet that uses PSCmdlet.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found