Complete PowerShell Error Handling Guide

PowerShell Error Handling Guide blog banner image

PowerShell is the primary command line and scripting language used by Windows operating systems. It lets you run programs and perform system management tasks from the terminal, and it is widely used by system administrators and developers to automate their workflows.

Error Handling is an important part of any scripting and automation. If something goes wrong, your PowerShell scripts shouldn’t just crash — they should identify that an error has occurred, and take action to retry the task, or alert you that something has gone wrong so that you can find and fix the cause.

This guide will provide you with a detailed understanding of Powershell error handling, including types of errors, error handling techniques, examples of how to implement error handling in your scripts, and best practices for throwing, catching, logging, and responding to errors.

Understanding the types of errors in PowerShell

There are two types of errors that you need to handle differently to ensure that your PowerShell scripts are reliable.

Terminating errors halt the execution of your command or script when they occur. These are usually exceptions, and can be handled using try/catch blocks (explained later in this article). The causes of terminating errors include syntax errors (when you mistype a command or provide invalid parameters) and internal errors in the application or command you are running.

Non-terminating errors do not halt the execution of your command or script — your PowerShell script will continue running after the error is encountered. Usually, non-terminating errors will display an error message before execution resumes and must be handled differently to terminating errors so that they do not cause your scripts to malfunction if their expected output is required later. Non-terminating errors may be caused by network timeouts, missing files, or permissions issues that, while not a critical exception or error in execution itself, will result in unintended behaviour if not handled.

Basic PowerShell error handling concepts (try, catch, finally, and $ErrorActionPreference)

Terminating errors and exceptions are thrown (the error occurs) and caught (code is executed to handle the error). Uncaught errors will cause execution of your Powershell script to halt. By encapsulating your code in try, catch, and finally blocks, you can manage these kinds of errors.

If code that is run in a try block throws an error, the block of code in the corresponding catch block will be run to handle the error (allowing execution to continue if appropriate). Any cleanup tasks that you want to run whether an error occurred or not can be added to a finally block. This is demonstrated with a full code example further down this page.

Handling non-terminating errors is done differently, as an error isn’t thrown to halt execution, and thus can’t be caught. Instead, the error is stored in the $Error variable, an array of errors that can be accessed at any point in your PowerShell scripts to see if a preceding statement generated a non-terminating error, as shown in this example:

Get-ChildItem -Path “C:\fake_path”

if ($Error) {

Write-Host “Error occurred: $($Error[0])” # Display the most recent error as a string

$Error.Clear() # Clear the error

}

Above, the Get-ChildItem PowerShell command generates a non-terminating error if the filesystem path it is supplied does not exist (in this case C:\fake_path). The error is recorded in the $Error variable, which is then checked and handled.

If you want to assign error output from a particular command to a custom variable, you can use the -ErrorVariable parameter (note that in this case, the error variable is not an array):

Get-ChildItem -Path “C:\fake_path” -ErrorVariable customError

if ($customError) {

Write-Host “Error occurred: $customError” # Display the error as a string

}

You can also turn non-terminating errors into terminating errors and handle them with try/catch blocks. You can do this for every non-terminating error encountered in your script by setting the global $ErrorActionPreference variable to Stop:

$ErrorActionPreference = “Stop”

Or, if you only want to do so for errors for a single command, you can set the -ErrorAction Parameter:

Get-ChildItem -Path “C:\fake_path” -ErrorAction Stop

Implementing try/catch/finally blocks in PowerShell

Below is an example PowerShell script that demonstrates the syntax and structure of try/catch/finally blocks, showing how to use multiple catch blocks for different exception types, and how to use a finally block to clean up and handle any remaining errors. First, here’s a single error being handled using a try/catch block:

try {

# Attempt a file operation that fails

Get-Content -Path “C:\fake_path\fake_file.txt” -ErrorAction Stop

} catch {

Write-Host “Exception caught: $($_.Exception.Message)”

}

You can also handle multiple different types of potential errors in a single try block, handling each with its own catch block:

try {

# Each of the below commands will throw a terminating error of a different type

Get-Content -Path “C:\fake_path\fake_file.txt” -ErrorAction Stop # Attempt a file operation that fails to throw a ItemNotFoundException

$null.fakeFunction() # Attempt to run a non-existent method on a null object to throw a RuntimeException

$divideZero = 1/0 # Divide by zero to throw an exception that won’t be specifically caught

} catch [System.Management.Automation.ItemNotFoundException] { # Catch the specific error thrown by Get-Content

Write-Host “Item not found exception caught: $($_.Exception.Message)”

} catch [System.Management.Automation.RuntimeException] { # Catch the specific error thrown by $null.fakeFunction

Write-Host “Runtime exception caught: $($_.Exception.Message)”

} catch { # Catch all other errors

# General catch block for any other exceptions

Write-Host “General exception caught: $($_.Exception.Message)”

} finally { # The finally block is always executed whether an exception was thrown or not.

Write-Host “Executing the finally block.”

$Error.Clear() # This could, for example, be used to clean up non-terminating errors.

}

The purpose of each statement is explained in the code so that you can see the full context of how try, catch, and finally statements work together. Note that as multiple terminating errors occur in the same try block, only the first error will be caught, handled, and then the finally block will be executed. Once this error is fixed, subsequent errors will be caught when the script is executed.

Advanced error handling techniques and examples

It is also possible to nest try/catch blocks, so that errors ‘bubble’ up through them. This lets you handle specific errors in inner try/catch blocks, and handle any uncaught or re-thrown errors, even ones from inside your inner catch blocks, in your outer blocks. For example, you could use nested blocks to handle specific errors, and then use a single outer block to catch and log all errors rather than repeating the code to log them in every inner catch block.

try { # Beginning of the outer catch block

try { # Beginning of the inner catch block

# Include potentially error-causing code here

Get-Content -Path “C:\fake_path\fake_file.txt” -ErrorAction Stop

} catch [System.Management.Automation.ItemNotFoundException] { # Catch statement for the inner catch block that specifically handles ItemNotFoundException

Write-Host “Inner try block file not found exception caught: $($_.Exception.Message)”

} catch { # Catch statement for the inner catch block that handles all other exceptions

Write-Host “Inner try block exception caught: $($_.Exception.Message)”

throw # Re-throw the exception so that it will bubble up to the outer try/catch block

}

} catch { # Catch statement for the outer catch block

Write-Host “Outer try block exception caught: $($_.Exception.Message)” # Handle all errors re-thrown in the inner catch blocks here for clean up, logging, and alerting tasks

}

Note in the above example, the ItemNotFoundException is not re-thrown, so it won’t bubble up to be caught by the outer catch block.

As you start expanding your PowerShell scripts to cover your own use-cases, you will likely want to be able to introduce your own custom exceptions and PowerShell error records:

try {

$customException = New-Object Exception “This is a custom error!” # Create and throw a custom error

# Create a custom Error Record

$customErrorRecord = New-Object System.Management.Automation.ErrorRecord (

$customException,

“CustomErrorID”,

[System.Management.Automation.ErrorCategory]::NotSpecified, # Sets the ErrorRecord category to NotSpecified

$null # Specify no specific target object for this error

)

throw $customErrorRecord

} catch {

# Catch and handle the custom error record

Write-Host “Error Message: $($_.Exception.Message)”

Write-Host “Error ID: $($_.FullyQualifiedErrorId)”

}

Above, you can see that no target object is specified (as it is set to $null). You could instead replace this with a file path or other reference and add further detail to the exception text to make the custom error more informative.

Best practices in PowerShell error handling

There are several best practices you should follow when writing your PowerShell scripts to ensure that error handling is effective:

  • Write clear and predictable error messages: Your error messages should be descriptive and include enough detail from the Exception or ErrorRecord object to identify the specific cause of an error.
  • Ensure that your scripts can continue running (or exit gracefully) if an error is encountered: If your scripts are running other tasks, you may want to handle the error while they continue on. Errors that prevent your script from continuing should cause your script to exit with an exit code, and the result of any errors should be logged and reported.
  • Regularly test your error handling and reporting infrastructure: Your PowerShell automatons are useless if they fail without you realising. Regularly test your scripts by introducing errors to make sure that your error handling works, the details are logged, and that you are alerted.

Error handling is an important feature of PowerShell scripting and is helpful while you develop your scripting and automation skills. Properly implementing error handling, including correctly throwing errors, using try/catch/finally blocks and leveraging $ErrorActionPreference will help you learn PowerShell syntax, and give you better insight into any problems your scripts encounter, and help you better manage them.

Next Steps

Building an efficient and effective IT team requires a centralized solution that acts as your core service deliver tool. NinjaOne enables IT teams to monitor, manage, secure, and support all their devices, wherever they are, without the need for complex on-premises infrastructure.

Learn more about Ninja Endpoint Management, check out a live tour, or start your free trial of the NinjaOne platform.

You might also like

Ready to become an IT Ninja?

Learn how NinjaOne can help you simplify IT operations.

Watch Demo×
×

See NinjaOne in action!

By submitting this form, I accept NinjaOne's privacy policy.

Start a Free Trial of the
#1 Endpoint Management Software on G2

No credit card required, full access to all features

NinjaOne Terms & Conditions

By clicking the “I Accept” button below, you indicate your acceptance of the following legal terms as well as our Terms of Use:

  • Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms.
  • Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party.
  • Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library belonging to or under the control of any other software provider.
  • Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations.
  • Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks.
  • Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script.
  • EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).