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.

Clarify the intended behavior/documentation/terminology of terminating errors

See original GitHub issue

For the larger context, see Our Error Handling, Ourselves - time to fully understand and properly document PowerShell’s error handling.

  • The documentation (about_Preference_Variables and about_Throw) only makes the distinction between non-terminating and terminating errors, neglecting to distinguish between the two fundamentally different types of terminating errors:

    • statement-terminating errors, as generated by some cmdlets and by .NET exceptions
    • script-terminating errors, as generated with the Throw keyword or potentially by escalation via -ErrorAction or $ErrorActionPreference.
  • The documentation mistakenly claims that $ErrorActionPreference exclusively applies to non-terminating errors, whereas it controls the behavior of both types of terminating errors too.

On a personal note, the conflation of the two types of terminating errors in the documentation has caused me years of confusion.


The sample cmdlet used below that generates a terminating error is courtesy of @PetSerAl.

Statement-terminating errors

Steps to reproduce

# Define New-TerminatingError cmdlet whose sole purpose is to generate a 
# statement-terminating error.
Add-Type '
 using System.Management.Automation; 
 [Cmdlet("New", "TerminatingError")]
 public class NewTerminatingErrorCmdlet : Cmdlet { 
   protected override void ProcessRecord() { 
     ThrowTerminatingError(new ErrorRecord(new System.Exception(), "Error", ErrorCategory.NotSpecified, null));
   } 
 }' -PassThru | % Assembly | Import-Module

# Per the documentation, this should only affect *non-terminating* errors.
$ErrorActionPreference = 'Stop'

# Should only terminate the statement (pipeline), not the script.
New-TerminatingError | % {} -End { 'end of pipeline' }

'end of script'

Expected behavior

Note: Expected based on the current documentation - arguably, the actual behavior makes more sense.

New-TerminatingError : Exception of type 'System.Exception' was thrown.
...
end of script

Actual behavior

$ErrorActionPreference = 'Stop' did take effect for the pipeline-terminating error and aborted the script:

New-TerminatingError : Exception of type 'System.Exception' was thrown.
...

Script-terminating errors

# Per the documentation, this should only affect *non-terminating* errors.
$ErrorActionPreference = 'SilentlyContinue'

# Should abort the script, irrespective of the $ErrorActionPreference value, according
# to the documentation.
Throw "I'm outta here"

'end of script'

Expected behavior

The script should be aborted, and the error message passed to Throw should be displayed.

I'm outta here
...

Actual behavior

$ErrorActionPreference = 'SilentlyContinue' caused the Throw statement to be ignored.

Note that, according to the documentation, Ignore is an invalid value for $ErrorActionPreference and should only be used with the -ErrorAction common parameter.
However, it is accepted and somewhat takes effect: it ignores the Throw error, yet still records it in $Error.

end of script

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)

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Reactions:1
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
mklement0commented, Mar 15, 2018

@alx9r:

No immediate plans, given the ongoing discussions, but I’ll keep you posted (or vice versa, if you feel inclined to take it on).

I’d first like to better understand what the original design was (and where things went wrong) and if there’s even a fundamental willingness to entertain the thought of a change by the powers that be - which would obviously a massively breaking change.

1reaction
iSazonovcommented, Feb 26, 2018

@mklement0 I guess the best way is to collect such proposals/specifications as RFC to implement them in next version (7.0?).

Read more comments on GitHub >

github_iconTop Results From Across the Web

Terminating Errors - PowerShell
When a terminating error occurs, the cmdlet should report the error by calling the System.Management.Automation.Cmdlet.Throwterminatingerror* ...
Read more >
about Try Catch Finally - PowerShell
If a terminating error occurs in the try block, PowerShell searches for an appropriate catch block. If one is found, the statements in...
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 >
Powershell: terminating exception still continues to next ...
PowerShell has two types of terminating errors, which the documentation currently conflates, unfortunately: Statement-terminating errors ...
Read more >
Terminating & Non-Terminating error behavior
I am trying to manage error handling in a script, that uses a self made module. What I would like to have is...
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