Windows PowerShell has a robust error handling capability with PowerShell try catch blocks. And PowerShell 7 introduced new features, making troubleshooting even easier. In this article, I will show you how to use PowerShell’s built-in error handling features to help debug your scripts when there are problems.
First, it helps to have a good understanding of errors within PowerShell. A common operation is to test the network connection to another system using the Test-Connect cmdlet. The example is using a computer name of fakesystem
, that isn’t going to work, and only 1
ICMP ping is being sent to simplify testing (default is 4
ICMP pings).
Test-Connection "fakesystem" -Count 1
As expected the operation failed, but it would be nice to output a nicer error message then that. To “catch” the error, we use a try-catch
block. By wrapping our code in this block, any error will be caught and we can then output an appropriate message or take some other action. Let’s give this a try below. You should expect to see Error
in the output.
Try { Test-Connection "fakesystem" -Count 1 } Catch { "Error" }
Instead you see the same error message as before, ...No such host is known...
, but shouldn’t we see Error
? The Test-Connection
cmdlet outputs something called a non-terminating error. There are two types of errors, Terminating and Non-Terminating. Terminating errors stop execution whereas non-terminating writes to the error stream but does not stop the pipeline execution. The PowerShell try-catch
block only catches terminating errors.
How do we make Test-Connection
throw a terminating error then? Thankfully there is a handy parameter available to most functions called, ErrorAction. You can configure the cmdlets error handling behavior to throw a terminating error by specifying Stop
as the value.
Try { Test-Connection "fakesystem" -Count 1 -ErroAction 'Stop' } Catch { "Error" }
Now when you run the above code, you will get Error
as the output. The output of just what we define for the error message is much more concise and opens up the door to customized error messages. Often though, instead of catching all errors equally, maybe you want to customize how each exception type is handled. try-catch
can do this, but you first need to know what the exception is.
After running the above code, you can inspect the global $Error
variable and as you can see below what exception type was thrown:
$Error[0].Exception.GetType().FullName
Now that we know the specific exception type is System.Net.NetworkInformation.PingException
we can catch just this error. The code below will output Ping Exception
and as you can tell we can chain multiple exception types with a default value at the end using PowerShell try catch blocks.
Try { Test-Connection "fakesystem" -Count 1 -ErrorAction 'Stop' } Catch [System.Net.NetworkInformation.PingException] { "Ping Exception" } Catch { "Unknown Exception" }
All this is very cool and useful but how does PowerShell 7 help us here? As you’ve no doubt noticed, unless you are turning everything into terminating errors using ErrorAction 'Stop'
, this will quickly become difficult to manage.
Related article: Understanding the PowerShell 7 Error Variable
PowerShell 7 has a brand new error view option called ConciseView
. Set the preference variable $ErrorView
to 'ConciseView'
or to get the same view as before set the variable to 'NormalView'
. With ConciseView
turned on (the default in PowerShell 7) let’s see what our output looks like now with the Test-Connection
example.
Test-Connection "fakesystem" -Count 1
Below is a view of each of the three ErrorView options and how they display the error of the Test-Connection
example.
That is a whole lot easier to digest! What if you need to dive into the error to understand what’s going on though? With PowerShell 7 there is a brand new cmdlet named Get-Error
. This cmdlet outputs a ton of very useful and interesting information.
If we run Get-Error
with no arguments, it outputs all the information on the last error to be shown. In this case, that of our Test-Connection
failure as shown below.
Get-Error
Woah, that is a lot more than expected! What’s great about this is that it displays not only the basic exception but also the InnerException
and a StackTrace
which dives into the internals and displays a lot of useful information, especially if we don’t really know what went wrong.
As you can tell, error handling in PowerShell is robust and can be well controlled. With the addition of a more concise view for errors in the console, and the additional added ability to easily dive into the underlying reasons for an error, PowerShell 7 has upped the game in helping you troubleshoot your functions, scripts, and modules!
When working with PowerShell try catch blocks in nested operations, you can implement multiple layers of error handling by using nested try-catch blocks. Each inner block can handle specific exceptions while allowing outer blocks to catch unhandled errors, creating a hierarchical error handling structure.
Yes, PowerShell try catch error handling can be implemented in background jobs and runspaces. However, you need to ensure proper error stream handling and use the -ErrorAction parameter appropriately since error handling behavior might differ in parallel execution contexts.
PowerShell try catch blocks have minimal performance overhead when used properly. However, excessive use of try-catch blocks in tight loops or high-frequency operations can impact script performance, so it’s recommended to implement them strategically in critical error-prone sections.
You can combine PowerShell try catch blocks with do-while or for loops to create retry mechanisms. This approach is particularly useful for handling transient network errors or resource-busy situations, allowing multiple attempts before throwing a final exception.
When implementing PowerShell try catch error handling, it’s recommended to use Write-Error for non-terminating errors and throw for terminating errors, combined with a logging mechanism that captures the $_.Exception details, timestamp, and context information for troubleshooting.