Understanding the PowerShell 7 Error Variable
As with any programming language, code will have errors and troubleshooting those problems can be difficult. Thankfully, PowerShell has a rich error object and several powerful tools to help debug your code.
With PowerShell 7, these tools become even more useful and error handling even easier. As the language evolves and becomes used in more places than ever, being able to quickly and efficiently troubleshoot a problem will prove invaluable to integrating the language into common workflows.
Understanding Errors in PowerShell
Broadly speaking, PowerShell errors fall into two categories, terminating and non-terminating. Though these concepts are worth articles in their own right, a terminating error implies that code execution is stopped when the error is thrown. A non-terminating error implies that the code will continue despite an error message being shown.
As you can see below, the text “This should never be shown”, is not shown, as the terminating error stops code execution. The function
throw will always return a terminating error.
Passwords Haven’t Disappeared Yet
123456. Qwerty. Iloveyou. No, these are not exercises for people who are brand new to typing. Shockingly, they are among the most common passwords that end users choose in 2021. Research has found that the average business user must manually type out, or copy/paste, the credentials to 154 websites per month. We repeatedly got one question that surprised us: “Why would I ever trust a third party with control of my network?
It is more difficult to arbitrarily generate a non-terminating error, but one easy way is to use the
Get-ChildItem cmdlet and ask the cmdlet to find a nonexistent directory. As you can tell the command
Write-Host "This text will show!", does in fact appear.
You can turn most non-terminating errors into terminating errors by modifying an individual cmdlet’s
Stop. For example,
Get-ChildItem "missing_dir" -ErrorAction 'Stop'
You might notice that in the previous output, there are two different views of the error information. Figure 1 shows the
NormalView of the
$ErrorView preference variable. This view was standard and traditional until PowerShell 7. Starting with PowerShell 7, the default view has changed to what you see in Figure 2 and that is of the
ConciseView. It dispenses with much of the decoration around the output, but as you might be able to tell, some information is not made available.
The Error Object Behind the Scenes
Underlying the data behind the error output is the
$Error object that is populated by PowerShell when errors are thrown. To view this data, you are able to output and walk through the information. The traditional way to get the last error thrown is by calling
$Error. This uses array notation to reference the error.
If you happen to mistype this command, you will overwrite the first object in the error collection with the new error, so be careful when referencing this object.
As you can see there is the same error as originally shown, but we want to view more of the data. By selecting all of the properties, we are able to see what’s available. As we will talk about in the next section, the
Get-Error cmdlet provides a rich view of this data, but it’s important to understand what is going on underneath.
By walking through each property we can see what information exists between the
Get-Error cmdlet and the
$Error object itself.
That brings us to the next PowerShell 7 addition and that is the
Get-Error cmdlet. To expand upon the
ConciseView and show far more detail, we can run the
Get-Error cmdlet and see the expanded details of the last error thrown.
There is a lot of information shown here, so let’s break down what is useful.
- Type – Basic Exception Information
- ErrorRecordMost of this information is from the
$Errorobject itself. The
FullyQualifiedErrorIdare all duplicated further in the
Get-Erroroutput. What is useful is the
- Type – An exception, but could be referencing the parent exception
- Message – The human-readable error message
- HResult – Traditional numerical error code that Windows has used since the early days of the operating system
- ItemName – The same as the
TargetObjectshown later in the
- SessionStateCategory – A series of values that errors fall into, this is an
- TargetSite – A set of information that exposes some of the internal PowerShell engine values and where the error itself is coming from
- StackTrace – This is the actual method signature of where the error itself came from and can help aid in why an error was shown
- Message – The human-readable error message
- Source – This is the source of where the error is coming from
- HResult – As discussed above, the traditional numerical error code from Windows
The object that the function, cmdlet, or code targets, in this case
A concatenated view of several different properties, breaking down to the below format:
<Error>: (<TargetObject>:<ObjectType>) [<Originating CmdLet>], <Exception Type>
Message property of the exception object combined with the fully-qualified name of the class where the exception originated.
- MyCommand – The originating cmdlet or function throwing the error
- ScriptLineNumber – Location within the file or ScriptBlock that the error is thrown
- OffsetInLine – The location within the line that the error was thrown
- HistoryId – The location from within the
Get-Historycmdlet that the error was thrown
- Line – The command throwing the error
- PositionMessage – Combined information for the error
- InvocationName – The cmdlet or function throwing the error
- CommandOrigin – In what context the error was thrown
Contained here is information on where in a script the error occurred. In this case, the error occurred on
line 1, but this will reflect the line of the error in the given
Unlike other programming languages, PowerShell provides a very rich error object to figure out what went wrong and help to debug troublesome code. With PowerShell 7, the ability to decipher errors is even easier with the introduction of the
Get-Error cmdlet. Furthermore, the
ConciseView of the
ErrorAction preference will keep the command line free from clutter and make coding even easier!