---
title: PowerShell Error Handling
tags: [powershell, error-handling, try-catch, exceptions, debugging, scripting]
---

# PowerShell Error Handling

Effective error handling is crucial for creating robust scripts that can recover from unexpected issues or fail gracefully. PowerShell provides a structured error handling mechanism similar to C# and other .NET languages.

**Parent Topic:** [[programming/PowerShell/Scripting|PowerShell Scripting and Programming]]
**Related:** [[programming/PowerShell/PowerShell|PowerShell Comprehensive Guide]]

## 1. Terminating vs. Non-Terminating Errors

Understanding the difference is key to catching errors.

*   **Non-Terminating Errors**: The command fails, but the script continues to the next line. Most standard cmdlets emit non-terminating errors by default (e.g., `Get-ChildItem "MissingFile"`).
*   **Terminating Errors**: The script (or pipeline) stops immediately. `Throw` creates a terminating error.

**Crucial Rule:** `Try-Catch` blocks *only* catch Terminating Errors.

## 2. The Try-Catch-Finally Block

### Basic Structure
```powershell
try {
    # Code that might throw a terminating error
    # We use -ErrorAction Stop to force standard errors to be terminating
    Get-Item "C:\NonExistentFile.txt" -ErrorAction Stop
}
catch {
    # Code that runs if an error occurs
    # $_ represents the error object caught
    Write-Warning "Caught an error: $_"
}
finally {
    # Code that runs ALWAYS (success or failure)
    # Good for cleanup (closing connections, files)
    Write-Host "Finished attempt."
}
```

### Why `-ErrorAction Stop`?
Since most cmdlets produce non-terminating errors, `try` won't catch them by default. Adding `-ErrorAction Stop` forces the error to be terminating, allowing the `catch` block to handle it.

## 3. Catching Specific Exceptions

You can have multiple `catch` blocks to handle different types of errors differently.

```powershell
try {
    $content = Get-Content "C:\Restricted\file.txt" -ErrorAction Stop
    $number = 1 / 0
}
catch [System.UnauthorizedAccessException] {
    Write-Error "Permission denied accessing the file."
}
catch [System.DivideByZeroException] {
    Write-Error "Math error: Cannot divide by zero."
}
catch {
    # Catch-all for any other error
    Write-Error "An unexpected error occurred: $($_.Exception.Message)"
}
```

To find the Exception Type, inspect a previous error in your console:
```powershell
$Error[0].Exception.GetType().FullName
```

## 4. The `$Error` Automatic Variable

PowerShell stores errors in the `$Error` array (0-indexed, most recent first).
*   `$Error[0]`: The most recent error.
*   `$Error.Clear()`: Clears the error history.

## 5. ErrorActionPreference

You can control error behavior globally or per-command.

*   **Continue** (Default): Display error, continue script.
*   **Stop**: Display error, stop script (catchable).
*   **SilentlyContinue**: No error display, continue script.
*   **Inquire**: Prompt user.

```powershell
# Global setting for the current scope
$ErrorActionPreference = "Stop"

# Per-command override
Remove-Item "C:\Temp\*" -ErrorAction SilentlyContinue
```

## 6. Throwing Custom Errors

You can generate your own terminating errors using `Throw`.

```powershell
function Connect-Server {
    param($Server)
    
    if (-not (Test-Connection $Server -Count 1 -Quiet)) {
        Throw "Server $Server is not reachable!"
    }
    
    Write-Host "Connected to $Server"
}
```

## 7. The `$_` Variable in Catch Blocks

Inside a `catch` block, `$_` (or `$PSItem`) represents the ErrorRecord object that was caught.

*   `$_.Exception.Message`: The concise error message.
*   `$_.InvocationInfo`: Details about where the error happened (line number, script name).
*   `$_.ScriptStackTrace`: The call stack trace.