try, catch, and finally
Prerequisites: Errors: terminating and non-terminating
try/catch handles terminating errors:
try {
$result = 10 / 0
'This line does not run'
} catch {
"Caught: $($_.Exception.Message)"
} finally {
'Finally always runs'
}
Caught: Attempted to divide by zero.
Finally always runs
- Inside
catch,$_is the error record;$_.Exception.Messageis the message. finallyruns whether or not an error happened — for cleanup like closing connections or deleting temp files.
catch doesn't see non-terminating errors
try {
Get-Item missing.txt
'try block finished'
} catch {
'caught it'
}
'---'
try {
Get-Item missing.txt -ErrorAction Stop
'try block finished'
} catch {
'caught it'
}
Get-Item: C:\demo\script.ps1:2
Line |
2 | Get-Item missing.txt
| ~~~~~~~~~~~~~~~~~~~~
| Cannot find path 'C:\demo\missing.txt' because it does not
| exist.
try block finished
---
caught it
Without -ErrorAction Stop, the error isn't terminating, so catch
never runs. Always add -ErrorAction Stop to cmdlets inside try (or
set $ErrorActionPreference = 'Stop').
Catching specific exceptions
function Read-Config {
param([string]$Path)
try {
Get-Content $Path -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop
} catch [System.Management.Automation.ItemNotFoundException] {
"No config at $Path, using defaults"
} catch [System.ArgumentException] {
"Config at $Path is not valid JSON"
} catch {
"Unexpected: $($_.Exception.GetType().Name)"
}
}
Set-Content bad.json '{ "port": '
Read-Config missing.json
Read-Config bad.json
No config at missing.json, using defaults
Config at bad.json is not valid JSON
Catch blocks are checked in order; list the most specific types first. To
find a type to catch, look at $_.Exception.GetType().FullName in a
general catch.
throw
function Set-Discount {
param([double]$Percent)
if ($Percent -lt 0 -or $Percent -gt 50) {
throw "Discount must be between 0 and 50, got $Percent"
}
"Discount set to $Percent%"
}
Set-Discount 20
try { Set-Discount 80 } catch { "Error: $_" }
Discount set to 20%
Error: Discount must be between 0 and 50, got 80
In a catch block, throw on its own rethrows the current error — after
logging it, for example.
Common mistakes
- An empty
catch { }that hides every problem. At minimum, log the error. - Forgetting
-ErrorAction Stopand assumingcatchwill run.