Error Handling
Learn PowerShell error handling with try/catch/finally, error types, ErrorAction, trap statements, and best practices for writing robust scripts.
📖 5 min read📅 2026-02-10Scripting
Understanding Errors in PowerShell
PowerShell has two types of errors:
Terminating Errors
Stop execution immediately. Thrown by throw, .NET exceptions, and cmdlets with -ErrorAction Stop.
Non-Terminating Errors
Report an error but continue execution. Most cmdlet errors are non-terminating by default.
# Non-terminating: continues to the next item
Get-Item "nonexistent.txt", "C:\Windows"
# Error for nonexistent.txt, then shows C:\Windows
# Terminating: stops everything
throw "This stops execution"Try / Catch / Finally
The primary error handling mechanism:
try {
# Code that might fail
$content = Get-Content "nonexistent.txt" -ErrorAction Stop
Write-Host "File content: $content"
}
catch {
# Handle the error
Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red
}
finally {
# Always runs (cleanup code)
Write-Host "Operation complete"
}Catching Specific Exceptions
try {
$result = 10 / 0
}
catch [System.DivideByZeroException] {
Write-Host "Cannot divide by zero!"
}
catch [System.IO.FileNotFoundException] {
Write-Host "File not found!"
}
catch [System.UnauthorizedAccessException] {
Write-Host "Access denied!"
}
catch {
# Catch everything else
Write-Host "Unexpected error: $($_.Exception.Message)"
}Error Object Properties
try {
Get-Item "nonexistent.txt" -ErrorAction Stop
}
catch {
# The error record ($_) has many useful properties
Write-Host "Message: $($_.Exception.Message)"
Write-Host "Type: $($_.Exception.GetType().FullName)"
Write-Host "Category: $($_.CategoryInfo.Category)"
Write-Host "Target: $($_.TargetObject)"
Write-Host "Script: $($_.InvocationInfo.ScriptName)"
Write-Host "Line: $($_.InvocationInfo.ScriptLineNumber)"
Write-Host "Command: $($_.InvocationInfo.MyCommand)"
Write-Host "Stack: $($_.ScriptStackTrace)"
}ErrorAction Parameter
Control how individual commands handle errors:
# Stop: Convert to terminating error (catchable)
Get-Item "nonexistent.txt" -ErrorAction Stop
# SilentlyContinue: Suppress error messages
Get-Item "nonexistent.txt" -ErrorAction SilentlyContinue
# Continue: Show error but keep going (default)
Get-Item "nonexistent.txt" -ErrorAction Continue
# Inquire: Ask the user what to do
Get-Item "nonexistent.txt" -ErrorAction Inquire
# Ignore: Like SilentlyContinue but doesn't add to $Error
Get-Item "nonexistent.txt" -ErrorAction IgnoreErrorActionPreference
Set the default error behavior for the entire session or script:
# Make all errors terminating by default
$ErrorActionPreference = "Stop"
# Common in scripts:
$ErrorActionPreference = "Stop"
try {
# Now ALL errors are catchable
Get-Item "file1.txt"
Get-Content "file2.txt"
Set-Content "file3.txt" -Value "data"
}
catch {
Write-Error "Something failed: $_"
}
finally {
$ErrorActionPreference = "Continue" # Reset
}The $Error Variable
PowerShell keeps a history of all errors:
# Most recent error
$Error[0]
# All errors in session
$Error
# Number of errors
$Error.Count
# Clear error history
$Error.Clear()
# Check if last command succeeded
if ($?) {
Write-Host "Last command succeeded"
}
else {
Write-Host "Last command failed"
}Throw — Creating Custom Errors
# Simple throw
throw "Something went wrong!"
# Throw with a specific exception type
throw [System.IO.FileNotFoundException]::new("Config file not found")
# Conditional throw
function Set-Age {
param([int]$Age)
if ($Age -lt 0 -or $Age -gt 150) {
throw "Age must be between 0 and 150. Got: $Age"
}
Write-Host "Age set to $Age"
}
try {
Set-Age -Age -5
}
catch {
Write-Host "Validation error: $_" -ForegroundColor Red
}Write-Error vs Throw
# Write-Error: Non-terminating (continues execution)
function Test-WriteError {
Write-Error "Something went wrong"
Write-Host "This still runs!"
}
# Throw: Terminating (stops execution)
function Test-Throw {
throw "Something went wrong"
Write-Host "This never runs!"
}
# Use Write-Error for warnings/non-critical errors
# Use throw for critical errors that should stop executionPractical Error Handling Patterns
Pattern 1: Retry Logic
function Invoke-WithRetry {
param(
[scriptblock]$ScriptBlock,
[int]$MaxRetries = 3,
[int]$DelaySeconds = 5
)
$attempt = 0
$lastError = $null
while ($attempt -lt $MaxRetries) {
$attempt++
try {
Write-Host "Attempt $attempt of $MaxRetries..."
$result = & $ScriptBlock
return $result
}
catch {
$lastError = $_
Write-Warning "Attempt $attempt failed: $($_.Exception.Message)"
if ($attempt -lt $MaxRetries) {
Write-Host "Retrying in $DelaySeconds seconds..."
Start-Sleep -Seconds $DelaySeconds
}
}
}
throw "All $MaxRetries attempts failed. Last error: $lastError"
}
# Usage
Invoke-WithRetry -ScriptBlock {
Invoke-WebRequest "https://api.example.com/data" -TimeoutSec 10
} -MaxRetries 3 -DelaySeconds 5Pattern 2: Logging Errors
function Write-Log {
param(
[string]$Message,
[ValidateSet("INFO", "WARN", "ERROR")]
[string]$Level = "INFO"
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logEntry = "[$timestamp] [$Level] $Message"
Add-Content -Path "script.log" -Value $logEntry
switch ($Level) {
"ERROR" { Write-Host $logEntry -ForegroundColor Red }
"WARN" { Write-Host $logEntry -ForegroundColor Yellow }
default { Write-Host $logEntry }
}
}
# Usage in error handling
try {
Write-Log "Starting file processing" -Level INFO
$data = Get-Content "data.csv" -ErrorAction Stop
Write-Log "Processed $($data.Count) lines" -Level INFO
}
catch {
Write-Log "Failed to process file: $($_.Exception.Message)" -Level ERROR
Write-Log "Stack trace: $($_.ScriptStackTrace)" -Level ERROR
}Pattern 3: Cleanup with Finally
$connection = $null
try {
$connection = [System.Data.SqlClient.SqlConnection]::new($connectionString)
$connection.Open()
# Do database work...
$command = $connection.CreateCommand()
$command.CommandText = "SELECT * FROM Users"
$reader = $command.ExecuteReader()
}
catch {
Write-Error "Database error: $($_.Exception.Message)"
}
finally {
# Always close the connection
if ($connection -and $connection.State -eq 'Open') {
$connection.Close()
Write-Verbose "Database connection closed"
}
}Exercises
- Write a function that safely reads a file and returns
$nullwith a warning if not found - Create a script with retry logic that pings a server until it responds
- Build an error-logging function that writes to both console and log file
- Write a try/catch block that catches specific .NET exceptions differently
- Create a validation function that throws descriptive errors for invalid input
Next: File System Operations — learn to manage files and folders!