Code fails – whether because of reasons out of our control, or because we didn’t consider the situation it might fail. So what should you do in case your script throws a PowerShell Error?
Reason for PowerShell Error
Expired credentials, timeout connections, lack of permissions and genuine software bugs – each of these are potential problems which might fall our code over. And if we don’t handle the error, our script will simply throw and terminate. It’s certainly not a desired state.
Non-Terminating Errors
PowerShell has a concept of non-terminating errors – by default, it simply logs them and carries on running.
The way to stop the execution on the function level is to pass -ErrorAction Stop parameter.
#Non terminating errors
Write-Error "I just errored"
Write-Host "I'm Here!"
#We need to tell PowerShell to stop in case of error
Write-Error "Another failure" -ErrorAction Stop
Write-Host "I'm Here, again"
PowerShellTo change behaviour for the entire script, you can use $ErrorActionPreference variable to Stop
$ErrorActionPreference
#Or change it globally - this is what is done in production code
$ErrorActionPreference = "Stop"
Write-Error "Third failure"
Write-Host "I'm here, yet again"
PowerShellPowerShell Error handling with Try/Catch
Try/Catch is a way to handle the error – your script will not terminate.
You insert your code which you’re “trying” to the Try {} block, and what should happen in case it fails to the Catch {} block.
Catch runs only if Try threw the terminating error
#Let's revert to default
$ErrorActionPreference = 'Continue'
#Finally works always
function Start-Work
{
param (
[switch]$Die
)
Write-Host "Happily working" -ForegroundColor Green
if ($Die.IsPresent)
{
Throw "Aaaargh meeting has started"
}
return "Job done"
}
#Without try catch there's not much we can do - script crashes
#Start-Work -Die
#Try/Catch
try
{
Start-Work -Die
}
catch
{
Write-Host "Well that doesn't look good..."
Write-Host $_
#Providing Throw without any comment rethrows the error
#Throw
}
Write-Host "This is the end"
PowerShellWhen there’s a case when you always want to run some code regardless of whether it threw an error or not, you can use the finally {} block.
This is useful for some clean-up tasks, or to close a database connection.
#Let's revert to default
$ErrorActionPreference = 'Continue'
#Finally works always
function Start-Work
{
param (
[switch]$Die
)
Write-Host "Happily working" -ForegroundColor Green
if ($Die.IsPresent)
{
Throw "Aaaargh meeting has started"
}
return "Job done"
}
#Try/Catch
try
{
Start-Work -Die
}
catch
{
Write-Host "Well that doesn't look good..."
Write-Host $_
Throw
}
finally
{
Write-Host "Locking up office" -ForegroundColor Blue
}
PowerShellLooking inside the PowerShell Error
Error is an object, with many nested properties in it.
The fact different functions might organise their error objects differently doesn’t help.
You can check the actual message, invocation information etc.
PowerShell 7 displays errors in a more user-friendly view. It also introduced a Get-Error cmdlet to retrieve the last error.
#Investigating errors
Invoke-RestMethod -Uri qazedc.fds
#Only PowerShell v7 and newer
Get-Error
$Error[0].InvocationInfo
$Error[0].Exception
$Error[0].Exception.Message
$Error[0].Exception.StackTrace
#This line is useful for typed exceptions
$Error[0].exception.GetType().FullName
PowerShellHandling applications errors
As the shell, PowerShell can execute applications just like normal cmdlets.
But applications rely on exit codes – which are not native to PowerShell.
By convention – 0 indicates a success, any other is treated as a failure.
You can check the exit code with $LastExitCode automatic variable.
PowerShell 7 again sees an improvement here, as it can handle application errors like normal functions.
try
{
Get-Command -Name git -CommandType Application -ErrorAction Stop
}
catch
{
Throw "No git, everything fails"
}
#Not all native applications would return error
try
{
git --thiscommanddoesntexist
}
catch
{
Throw "Git has failed"
}
# That's why we have last exit code
$LASTEXITCODE
git --version
$LASTEXITCODE
git --thiscommanddoesntexist
if ($LASTEXITCODE -ne 0)ย
{
Throw "Git has failed"
}
PowerShellAre you still scared of PowerShell Errors?
I hope this video and article will help to tame them.
You’ve seen what causes an error, what a non-terminating error is, and how to handle terminating errors with Try/Catch.
You should see fewer broken code executions after implementing all these features!
Additional materials
LinkedIn Cheat Sheet. We had a great discussion about error handling. Click here.
Short TikTok video
Want to learn more about PowerShell?
You can learn how to use Windows PowerShell with my PowerShell course for IT Professionals course.
Or if you’re already familiar with PowerShell, check out the PowerShell Best Practices ebook.
Finally, you can find more code examples on my GitHub.