A warning on $ErrorActionPreference and Try/Catch for .NET developers

I recently stumbled upon a PowerShell Script from a .NET Developer/Architect who shall remain nameless, which contained this :

# set error action preference so errors don't stop and the trycatch 
# kicks in to handle gracefully
$ErrorActionPreference = "Continue" 
try {
catch {

Let me this say this bluntly : this is a HUGE misunderstanding of error handling in PowerShell.
Yes, PowerShell is based on the .NET Framework. Yes, it understands the different types of exceptions which are in the Framework class library. Yes, it uses Try/Catch or Try/Catch/Finally blocks to handle errors, like in C#, but there are differences.

In C#, when can choose to handle exceptions using Try/Catch or to not handle the exception directly in the current method and let the CLR look for a Catch block in another method somewhere up the call stack.

In PowerShell, we generally don’t use the term “exception”, we use the term “error” more often, but that’s mainly a terminology thing.

The big catch (pun intended) is that Powershell have terminating errors and non-terminating errors. A terminating error is raised by a cmdlet when something is wrong, so wrong that it cannot continue processing any other items in the pipeline and it has to stop immediately. Generally, this is because the cmdlet doesn’t know what the hell you are talking about ( a syntax or a type-related error).

A non-terminating error is raised by a cmdlet when something is wrong but it does not prevent the cmdlet from processing any other items. Here is a example of a non-terminating error :

Non-Terminating error

We can see that Get-ChildItem raises an error because it cannot find the file DoesNotExist.txt, but it keeps going and processes any other file names we specified.

The second part of the catch (pun intended again), and this is where many PowerShell beginners get tripped up, is that the Catch block will execute only if a cmdlet in the Try block raises a terminating error. So, the Get-ChildItem example above would not trigger the Catch block.

The solution : either you set $ErrorActionPreference to “Stop” or at the cmdlet level, you set the parameter -ErrorAction to “Stop” to convert any error from that cmdlet to a terminating error. Personally, I prefer the latter because I don’t like to mess with global variables from within my scripts.

terminating error

This time, Get-ChildItem stops immediately and doesn’t process any other file.
So, how do we correct the script to ensure that the Catch block will actually be executed when an error occurs in the Try block ?

Try {
    # cmdlets which might raise terminating or non-terminating errors
    Get-ChildItem DoesNotExist.txt, DoesExist.txt -ErrorAction "Stop"
Catch {
    # Error handling code

Here, any error raised by the cmdlet Get-ChildItem will stop execution and execute whatever error handling code we put in our Catch block.

So, my advice to developers coming from C# or any other language to PowerShell is : don’t try to guess PowerShell behaviours based on the behaviours of other languages. In fact, as an engineer, you should never make assumptions.

Remember, the root cause of any bug is that someone, somewhere, made an assumption.

2 thoughts on “A warning on $ErrorActionPreference and Try/Catch for .NET developers”

Leave a Reply

Your email address will not be published. Required fields are marked *