diff --git a/reference/5.1/Microsoft.PowerShell.Core/About/about_Automatic_Variables.md b/reference/5.1/Microsoft.PowerShell.Core/About/about_Automatic_Variables.md index aa6467ae692..86336446e0a 100644 --- a/reference/5.1/Microsoft.PowerShell.Core/About/about_Automatic_Variables.md +++ b/reference/5.1/Microsoft.PowerShell.Core/About/about_Automatic_Variables.md @@ -1,7 +1,7 @@ --- description: Describes variables that store state information for PowerShell. These variables are created and maintained by PowerShell. Locale: en-US -ms.date: 02/10/2026 +ms.date: 04/02/2026 no-loc: [Reset, Current, Background, Blink, Bold, Foreground, Formatting, Hidden, Italic, Reset, Reverse, Underline, PSEventArgs, PSEventSubscriber, PSEdition] online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_automatic_variables?view=powershell-5.1&WT.mc_id=ps-gethelp schema: 2.0.0 @@ -160,8 +160,8 @@ use this automatic variable to determine the file to update. Contains an array of error objects that represent the most recent errors. The most recent error is the first error object in the array `$Error[0]`. -To prevent an error from being added to the `$Error` array, use the -**ErrorAction** common parameter with a value of **Ignore**. For more +To prevent a non-terminating error from being added to the `$Error` array, use +the **ErrorAction** common parameter with a value of **Ignore**. For more information, see [about_CommonParameters][53]. ### `$Event` diff --git a/reference/5.1/Microsoft.PowerShell.Core/About/about_CommonParameters.md b/reference/5.1/Microsoft.PowerShell.Core/About/about_CommonParameters.md index fe32c56dd06..c8aa37643dc 100644 --- a/reference/5.1/Microsoft.PowerShell.Core/About/about_CommonParameters.md +++ b/reference/5.1/Microsoft.PowerShell.Core/About/about_CommonParameters.md @@ -1,7 +1,7 @@ --- description: Describes the parameters that can be used with any cmdlet. Locale: en-US -ms.date: 01/18/2026 +ms.date: 04/02/2026 no-loc: [Confirm, Debug, ErrorAction, ErrorVariable, InformationAction, InformationVariable, OutBuffer, OutVariable, PipelineVariable, ProgressAction, Verbose, WarningAction, WarningVariable, WhatIf] online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_commonparameters?view=powershell-5.1&WT.mc_id=ps-gethelp schema: 2.0.0 @@ -109,14 +109,13 @@ the display of debugging messages when `$DebugPreference` isn't ### -ErrorAction Determines how the cmdlet responds to a non-terminating error from the command. -This parameter works only when the command generates a non-terminating error, -such as those from the `Write-Error` cmdlet. +This parameter overrides the value of the `$ErrorActionPreference` variable for +non-terminating errors generated by the command or the `Write-Error` cmdlet. ```yaml Type: ActionPreference Aliases: ea -Accepted values: Suspend, Ignore, Inquire, Continue, Stop, SilentlyContinue - +Accepted values: Break, Suspend, Ignore, Inquire, Continue, Stop, SilentlyContinue Required: False Position: Named Default value: Depends on preference variable @@ -129,9 +128,12 @@ variable for the current command. Because the default value of the `$ErrorActionPreference` variable is `Continue`, error messages are displayed and execution continues unless you use the `ErrorAction` parameter. -The `ErrorAction` parameter has no effect on terminating errors (such as -missing data, parameters that aren't valid, or insufficient permissions) that -prevent a command from completing successfully. +The `-ErrorAction` parameter doesn't prevent statement-terminating errors +(such as missing data, parameters that aren't valid, or insufficient +permissions) from stopping the current statement. However, when set to `Stop`, +it escalates non-terminating errors to script-terminating errors, making them +catchable by `try/catch`. For more information about error categories, see +[about_Error_Handling][15]. - `-ErrorAction:Break` Enters the debugger when an error occurs or an exception is raised. @@ -829,6 +831,7 @@ Mode LastWriteTime Length Name - [about_Preference_Variables][03] +- [about_Error_Handling][15] - [`Write-Debug`][11] - [`Write-Error`][12] - [`Write-Verbose`][13] @@ -844,4 +847,5 @@ Mode LastWriteTime Length Name [12]: xref:Microsoft.PowerShell.Utility.Write-Error [13]: xref:Microsoft.PowerShell.Utility.Write-Verbose [14]: xref:Microsoft.PowerShell.Utility.Write-Warning +[15]: about_Error_Handling.md diff --git a/reference/5.1/Microsoft.PowerShell.Core/About/about_Error_Handling.md b/reference/5.1/Microsoft.PowerShell.Core/About/about_Error_Handling.md new file mode 100644 index 00000000000..b7f5428356e --- /dev/null +++ b/reference/5.1/Microsoft.PowerShell.Core/About/about_Error_Handling.md @@ -0,0 +1,562 @@ +--- +description: Describes the types of errors in PowerShell and the mechanisms for handling them. +Locale: en-US +ms.date: 03/26/2026 +online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_error_handling?view=powershell-5.1&WT.mc_id=ps-gethelp +schema: 2.0.0 +title: about_Error_Handling +--- +# about_Error_Handling + +## Short description + +Describes the types of errors in PowerShell and the mechanisms for handling +them. + +## Long description + +PowerShell distinguishes three categories of errors: + +- Non-terminating errors +- Statement-terminating errors +- Script-terminating errors + +Understanding the distinction is essential for writing reliable scripts and +modules, because each category has different default behavior and requires +different handling techniques. + +Additionally, external (native) programs report failure through exit codes, +which PowerShell tracks separately from its own error system. + +## Types of errors + +### Non-terminating errors + +A non-terminating error reports a problem but doesn't stop the pipeline. The +command continues processing subsequent input objects. Non-terminating errors +are generated by: + +- The `Write-Error` cmdlet +- The `$PSCmdlet.WriteError()` method in advanced functions +- Cmdlets that encounter recoverable failures on individual input objects + +By default, PowerShell displays the error message and continues execution. + +```powershell +# Non-terminating error: the pipeline continues after the failure +'file1.txt', 'noSuchFile.txt', 'file3.txt' | ForEach-Object { + Get-Content $_ -ErrorAction Continue +} +``` + +In this example, `Get-Content` reports a non-terminating error for +`noSuchFile.txt` and then continues processing `file3.txt`. + +Non-terminating errors do **not** trigger `catch` or `trap` by default. + +### Statement-terminating errors + +A statement-terminating error stops the current statement (pipeline) from +running, but execution continues at the next statement in the script. +Statement-terminating errors are generated by: + +- The `$PSCmdlet.ThrowTerminatingError()` method in advanced functions and + compiled cmdlets +- Engine errors such as `CommandNotFoundException` (calling a command that + doesn't exist) and `ParameterBindingException` (invalid parameter arguments) +- .NET method calls that throw exceptions, such as `[int]::Parse('abc')` + +```powershell +# Statement-terminating error: Get-Item fails, but the next statement runs +Get-Item -Path 'C:\NoSuchFile.txt' +Write-Output 'This still runs' +``` + +Statement-terminating errors can be caught by `try/catch` and `trap`. + +> [!NOTE] +> `.ThrowTerminatingError()` doesn't consult the `-ErrorAction` parameter +> (except for the `Break` value, which enters the debugger). However, +> `$ErrorActionPreference` _does_ apply to statement-terminating errors +> through the engine's statement-level handler. For example, +> `$ErrorActionPreference = 'SilentlyContinue'` can suppress a +> statement-terminating error so that the script continues at the next +> statement. The `-ErrorAction` parameter can't do this. For details, see +> [The $ErrorActionPreference asymmetry][05]. + +### Script-terminating errors + +A script-terminating error unwinds the entire call stack. Execution stops +completely unless the error is caught by a `try/catch` block or `trap` +statement. Script-terminating errors are generated by: + +- The `throw` keyword +- Parse errors (syntax errors that prevent the script from being compiled) +- Non-terminating errors **escalated** by `-ErrorAction Stop` or + `$ErrorActionPreference = 'Stop'` in non-advanced contexts. For more + information, see [How escalation works][01]. +- Certain critical engine failures + +```powershell +# Script-terminating error: throw unwinds the call stack +function Test-Throw { + throw 'Critical failure' + Write-Output 'This never runs' +} + +Test-Throw +Write-Output 'This never runs either (unless caught)' +``` + +The `throw` keyword generates a script-terminating error by default. However, +`$ErrorActionPreference` _can_ suppress `throw` when set to `SilentlyContinue` +or `Ignore`. When calling an advanced function with +`-ErrorAction SilentlyContinue`, the parameter translates to a scope-local +`$ErrorActionPreference` value, so it also suppresses `throw` inside that +function. + +> [!NOTE] +> Even with `$ErrorActionPreference = 'Ignore'`, a `throw` that's suppressed +> still records an entry in `$Error`. The `Ignore` value only prevents `$Error` +> recording for **non-terminating** errors. + +> [!IMPORTANT] +> The terms _statement-terminating_ and _script-terminating_ describe the scope +> of impact, not the severity of the error. A statement-terminating error stops +> one statement. A script-terminating error stops the entire script and its +> callers. Both can be caught by `try/catch`. + +### External program errors + +External (native) programs don't participate in PowerShell's error system +directly. They report failure through a non-zero exit code, which PowerShell +stores in the `$LASTEXITCODE` automatic variable. + +```powershell +git clone https://example.com/nonexistent.git 2>$null +if ($LASTEXITCODE -ne 0) { + Write-Error "git failed with exit code $LASTEXITCODE" +} +``` + +By default, a non-zero exit code from a native program: + +- Sets `$?` to `$false` +- Does **not** generate an `ErrorRecord` in `$Error` +- Does **not** trigger `catch` or `trap` + +PowerShell 7.3 added the experimental preference variable +`$PSNativeCommandUseErrorActionPreference`, which became a stable feature in +7.4. When you set this variable to `$true`, it causes a non-zero exit code to +emit a **non-terminating error** whose message states the specific exit code (a +`NativeCommandExitException`). This error respects `$ErrorActionPreference`, so +setting it to `Stop` promotes the error to a script-terminating error that can +be caught with `try`/`catch`. + +## Error state variables + +PowerShell maintains several automatic variables that reflect the current error +state. + +### `$?` + +Contains `$true` if the last operation succeeded and `$false` if it produced +any error (non-terminating or terminating). For native commands, `$?` is set +based on the exit code: `$true` for exit code `0`, `$false` otherwise. + +```powershell +Get-Item -Path 'C:\NoSuchFile.txt' 2>$null +$? # False +``` + +### `$Error` + +An `ArrayList` that stores the most recent error records, with the most recent +error at index `0`. The list holds up to `$MaximumErrorCount` entries (default +256). + +All terminating errors are added to `$Error`. For terminating errors, `Ignore` +suppresses display but still records the error in `$Error`. All non-terminating +are added to `$Error` unless `-ErrorAction Ignore` is used on non-terminating +errors, which prevents both display and recording. + +### `$LASTEXITCODE` + +Contains the exit code of the last native program that ran. A value of `0` +conventionally indicates success. Any non-zero value indicates failure. This +variable isn't affected by PowerShell cmdlet errors. + +## Control error behavior + +### The `-ErrorAction` common parameter + +The `-ErrorAction` common parameter overrides `$ErrorActionPreference` for a +single command. It controls how PowerShell responds to **non-terminating** +errors from that command. + +| Value | Behavior | +| ------------------ | -------------------------------------------------------------------- | +| `Continue` | Display the error and continue (default) | +| `SilentlyContinue` | Suppress display, add to `$Error`, continue | +| `Ignore` | Suppress display and don't add to `$Error` | +| `Stop` | **Escalate** to a terminating error (see [How escalation works][01]) | +| `Inquire` | Prompt the user for a decision | +| `Break` | Enter the debugger | + +`-ErrorAction` doesn't change the behavior of errors generated by +`$PSCmdlet.ThrowTerminatingError()`. Those errors are always +statement-terminating regardless of the caller's preference. + +### The `$ErrorActionPreference `variable + +The `$ErrorActionPreference` preference variable applies to all commands in the +current scope and child scopes. It accepts the same values as `-ErrorAction`. + +```powershell +$ErrorActionPreference = 'Stop' +# All non-terminating errors in this scope now become terminating +Write-Error 'This now throws' # Generates ActionPreferenceStopException +``` + +When `-ErrorAction` is specified on a command, it takes precedence over +`$ErrorActionPreference` for that command. + +### How escalation works + +When `-ErrorAction Stop` or `$ErrorActionPreference = 'Stop'` is in effect, +PowerShell converts non-terminating errors into terminating errors using the +following mechanism: + +1. A cmdlet calls `WriteError()` internally to emit a non-terminating error. +1. The engine checks the effective `ErrorAction` preference for the command. +1. Because the preference is `Stop`, the engine creates an + `ActionPreferenceStopException` that wraps the original error record. +1. If caught by `catch`, the original error information is accessible through + `$_.Exception.ErrorRecord`. + +The scope of the escalated error depends on context: + +- In **non-advanced** scripts, functions, or script blocks, setting + `$ErrorActionPreference = 'Stop'` escalates to a **script-terminating** + error. The error propagates up the call stack. +- In **advanced** functions and script blocks (those with `[CmdletBinding()]`), + the error remains **statement-terminating**. Execution continues at the next + statement after the call. +- Passing `-ErrorAction Stop` to an advanced function has the same effect as + setting `$ErrorActionPreference = 'Stop'` inside it, because `-ErrorAction` + translates to a scope-local `$ErrorActionPreference` value. + +### Escalation examples + +- NON-advanced: script-terminating ('after' does NOT print) + + ```powershell + & { + param() + $ErrorActionPreference = 'Stop' + Get-Item 'NoSuchPath' + } 2>$null + 'after' + ``` + +- ADVANCED: statement-terminating ('after' DOES print) + + ```powershell + & { + [CmdletBinding()] + param() + $ErrorActionPreference = 'Stop'; Get-Item 'NoSuchPath' + } 2>$null + 'after' + ``` + +- Without `-ErrorAction Stop`: non-terminating, catch doesn't run + + ```powershell + try { + Write-Error 'This is non-terminating' + Write-Output 'Execution continues' + } catch { + Write-Output "Caught: $_" # Not reached + } + ``` + +- With `-ErrorAction Stop`: escalated to terminating + + ```powershell + try { + Write-Error 'This becomes terminating' -ErrorAction Stop + } catch { + Write-Output "Caught: $_" # Reached + } + ``` + +Escalated errors can be caught by their original exception type. The engine +unwraps the `ActionPreferenceStopException` to find the underlying exception: + +```powershell +try { + Get-Item -Path 'C:\NoSuchFile.txt' -ErrorAction Stop +} catch [System.Management.Automation.ItemNotFoundException] { + Write-Output "File not found: $($_.Exception.Message)" +} +``` + +### The `$ErrorActionPreference` asymmetry + +The `-ErrorAction` parameter and the `$ErrorActionPreference` variable behave +differently with terminating errors. It's important to understand this +asymmetry: + +- `-ErrorAction` only affects **non-terminating** errors. When a cmdlet calls + `$PSCmdlet.ThrowTerminatingError()`, the `-ErrorAction` parameter is ignored + (except for `Break`, which enters the debugger). The error is always thrown. + +- `$ErrorActionPreference` affects **both** non-terminating and + statement-terminating errors. The engine's statement-level error handler + reads `$ErrorActionPreference` (not the `-ErrorAction` parameter) and can + suppress a statement-terminating error when the value is `SilentlyContinue` + or `Ignore`. + +```powershell +function Test-Asymmetry { + [CmdletBinding()] + param() + $er = [System.Management.Automation.ErrorRecord]::new( + [System.InvalidOperationException]::new('test error'), + 'TestError', + [System.Management.Automation.ErrorCategory]::InvalidOperation, + $null + ) + $PSCmdlet.ThrowTerminatingError($er) +} + +# -ErrorAction SilentlyContinue does NOT suppress the error: +Test-Asymmetry -ErrorAction SilentlyContinue # Error is still thrown + +# $ErrorActionPreference DOES suppress the error: +$ErrorActionPreference = 'SilentlyContinue' +Test-Asymmetry # Error is silently suppressed, script continues +$ErrorActionPreference = 'Continue' +``` + +> [!IMPORTANT] +> `$ErrorActionPreference` can't suppress errors that have +> `SuppressPromptInInterpreter` set to `true`. These always propagate +> regardless of the preference variable. Examples of this type of error +> include: +> +> - `ActionPreferenceStopException` from `-ErrorAction Stop` escalation +> - Errors inside PowerShell class methods +> - `PipelineStoppedException` + +## Handle errors + +### `try/catch/finally` + +Use `try/catch/finally` to handle statement-terminating and script-terminating +errors. When an error occurs inside a `try` block, PowerShell searches for a +matching `catch` block. The `finally` block always runs, whether or not an +error occurred. + +```powershell +try { + $result = Get-Content -Path 'data.txt' -ErrorAction Stop +} +catch [System.Management.Automation.ItemNotFoundException] { + Write-Warning 'Data file not found, using defaults.' + $result = 'default' +} +catch { + Write-Warning "Unexpected error: $_" +} +finally { + Write-Verbose 'Cleanup complete.' -Verbose +} +``` + +Inside a `try` block, the engine sets an internal flag that causes non- +terminating errors escalated by `-ErrorAction Stop` or +`$ErrorActionPreference = 'Stop'` to propagate to the `catch` block. This +is designed behavior, not a special case. + +For full syntax details, see [about_Try_Catch_Finally][12]. + +### `trap` + +The `trap` statement handles terminating errors at the scope level. When an +error occurs anywhere in the enclosing scope, the `trap` block runs. + +- **Default** (no `break` or `continue`): The error is displayed and execution + continues at the next statement after the one that caused the error. +- **`continue`** in the trap: Suppresses the error message and resumes at the + next statement. +- **`break`** in the trap: The error propagates to the parent scope. + +```powershell +trap [System.Management.Automation.CommandNotFoundException] { + Write-Warning "Command not found: $($_.TargetObject)" + continue +} + +NonsenseCommand # Trap fires, execution continues +Write-Output 'This runs because the trap used continue' +``` + +For full syntax details, see [about_Trap][11]. + +## Reporting errors in functions and scripts + +When writing functions and scripts, choose the error-reporting mechanism that +matches the severity of the failure. + +### Non-terminating - use `Write-Error` + +Use `Write-Error` when the function can continue processing other input. This +is appropriate for pipeline functions that process multiple objects and +encounter failures on individual items. + +```powershell +function Test-Path-Safe { + [CmdletBinding()] + param([Parameter(ValueFromPipeline)][string]$Path) + process { + if (-not (Test-Path $Path)) { + Write-Error "Path not found: $Path" + return + } + $Path + } +} +``` + +> [!NOTE] +> In advanced functions (those with `[CmdletBinding()]`), use +> `$PSCmdlet.WriteError()` instead of `Write-Error` to ensure that `$?` is +> properly set to `$false` in the caller's scope. The `Write-Error` cmdlet +> doesn't always set `$?` correctly. + +### Statement-terminating - use `$PSCmdlet.ThrowTerminatingError()` + +Use `$PSCmdlet.ThrowTerminatingError()` when the function can't continue at all +but the caller should decide how to handle the failure. This is the recommended +approach in advanced functions. + +```powershell +function Get-Config { + [CmdletBinding()] + param([string]$Path) + + if (-not (Test-Path $Path)) { + $er = [System.Management.Automation.ErrorRecord]::new( + [System.IO.FileNotFoundException]::new("Config file not found: $Path"), + 'ConfigNotFound', + [System.Management.Automation.ErrorCategory]::ObjectNotFound, + $Path + ) + $PSCmdlet.ThrowTerminatingError($er) + } + + Get-Content $Path | ConvertFrom-Json +} +``` + +After the error leaves the function, the caller treats it as a non-terminating +error by default. The caller can escalate it with `-ErrorAction Stop`. + +### Script-terminating - use `throw` + +Use `throw` when recovery isn't possible and the entire script should stop. + +```powershell +$config = Get-Content 'config.json' -ErrorAction SilentlyContinue | + ConvertFrom-Json + +if (-not $config) { + throw 'Cannot proceed without a valid configuration file.' +} +``` + +### Which mechanism to use + +- When processing multiple inputs where some may fail, use `Write-Error` or + `$PSCmdlet.WriteError()`. +- If the function can't continue, use `$PSCmdlet.ThrowTerminatingError()` and + let the caller decide how to handle it. +- If the entire script must stop immediately, use `throw`. + +## Summary of error types + +The following tables summarize the properties and behaviors of the different +error types in PowerShell. + +### Non-terminating error + +[Non-terminating errors][02] can be generated by `Write-Error` or +`$PSCmdlet.WriteError()`. + +| Attribute | Description | +| ------------------------------------ | ------------------------------- | +| Scope of impact | Pipeline continues | +| Caught by `catch` | No (unless escalated) | +| Caught by `trap` | No (unless escalated) | +| Added to `$Error` | Yes (unless `Ignore`) | +| Sets `$?` to `$false` | Yes | +| Affected by `-ErrorAction` | Yes | +| Affected by `$ErrorActionPreference` | Yes | + +### Statement-terminating error + +[Statement-terminating errors][04] can be generated by +`ThrowTerminatingError()`, engine errors, .NET method exceptions, or +`-ErrorAction Stop` in advanced contexts. + +| Attribute | Description | +| ------------------------------------ | ----------------------------------------- | +| Scope of impact | Current statement stops; script continues | +| Caught by `catch` | Yes | +| Caught by `trap` | Yes | +| Added to `$Error` | Yes | +| Sets `$?` to `$false` | Yes | +| Affected by `-ErrorAction` | No (`Break` only) | +| Affected by `$ErrorActionPreference` | Yes (can suppress) | + +### Script-terminating error + +[Script-terminating errors][03] can be generated by `throw`, parse errors, or +`-ErrorAction Stop` in non-advanced contexts. + +| Attribute | Description | +| ------------------------------------ | ----------------------------- | +| Scope of impact | Call stack unwinds | +| Caught by `catch` | Yes | +| Caught by `trap` | Yes | +| Added to `$Error` | Yes | +| Sets `$?` to `$false` | Yes | +| Affected by `-ErrorAction` | No | +| Affected by `$ErrorActionPreference` | `throw`: Yes (can suppress) | +| Affected by `$ErrorActionPreference` | Escalated: depends on context | + +## See also + +- [about_Automatic_Variables][06] +- [about_CommonParameters][07] +- [about_Preference_Variables][09] +- [about_Output_Streams][08] +- [about_Throw][10] +- [about_Trap][11] +- [about_Try_Catch_Finally][12] + + +[01]: #how-escalation-works +[02]: #non-terminating-errors +[03]: #script-terminating-errors +[04]: #statement-terminating-errors +[05]: #the-erroractionpreference-asymmetry +[06]: about_Automatic_Variables.md +[07]: about_CommonParameters.md +[08]: about_Output_Streams.md +[09]: about_Preference_Variables.md +[10]: about_Throw.md +[11]: about_Trap.md +[12]: about_Try_Catch_Finally.md diff --git a/reference/5.1/Microsoft.PowerShell.Core/About/about_Preference_Variables.md b/reference/5.1/Microsoft.PowerShell.Core/About/about_Preference_Variables.md index 5c8102aecaa..08fe9c6a869 100644 --- a/reference/5.1/Microsoft.PowerShell.Core/About/about_Preference_Variables.md +++ b/reference/5.1/Microsoft.PowerShell.Core/About/about_Preference_Variables.md @@ -1,7 +1,7 @@ --- description: Variables that customize the behavior of PowerShell. Locale: en-US -ms.date: 12/01/2025 +ms.date: 04/02/2026 online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_preference_variables?view=powershell-5.1&WT.mc_id=ps-gethelp schema: 2.0.0 title: about_Preference_Variables @@ -121,7 +121,8 @@ Cmdlets and functions are assigned a risk of **High**, **Medium**, or **Low**. When the value of the `$ConfirmPreference` variable is less than or equal to the risk assigned to a cmdlet or function, PowerShell automatically prompts you for confirmation before running the cmdlet or function. For more information -about assigning a risk to cmdlets or functions, see [about_Functions_CmdletBindingAttribute][65]. +about assigning a risk to cmdlets or functions, see +[about_Functions_CmdletBindingAttribute][65]. If the value of the `$ConfirmPreference` variable is **None**, PowerShell never automatically prompts you before running a cmdlet or function. @@ -169,11 +170,12 @@ Cmdlets and functions that might pose a risk to the system have a **Confirm** parameter that you can use to request or suppress confirmation for a single command. -Most cmdlets and functions keep the default value of **Medium** for **ConfirmImpact**. -`$ConfirmPreference` is set to **High** by default. Therefore, it's rare that commands -automatically prompt for confirmation when users don't specify the **Confirm** parameter. -To extend automatic confirmation prompting to more cmdlets and functions, set the value -of `$ConfirmPreference` to **Medium** or **Low**. +Most cmdlets and functions keep the default value of **Medium** for +**ConfirmImpact**. `$ConfirmPreference` is set to **High** by default. +Therefore, it's rare that commands automatically prompt for confirmation when +users don't specify the **Confirm** parameter. To extend automatic confirmation +prompting to more cmdlets and functions, set the value of `$ConfirmPreference` +to **Medium** or **Low**. ### Examples @@ -379,9 +381,8 @@ script, cmdlet, or provider, such as the errors generated by the `Write-Error` cmdlet. The `$ErrorActionPreference` variable takes one of the -[`ActionPreference`][54] -enumeration values: **SilentlyContinue**, **Stop**, **Continue**, **Inquire**, -**Ignore**, or **Suspend**. +[`ActionPreference`][54] enumeration values: **SilentlyContinue**, **Stop**, +**Continue**, **Inquire**, **Ignore**, or **Suspend**. You can use a cmdlet's **ErrorAction** common parameter to override the preference for a specific command. @@ -390,27 +391,39 @@ The valid values are as follows: - **Continue**: (Default) Displays the error message and continues executing. - **Ignore**: Suppresses the error message and continues to execute the - command. The **Ignore** value is intended for per-command use, not for use as - saved preference. **Ignore** isn't a valid value for the - `$ErrorActionPreference` variable. + command. Unlike **SilentlyContinue**, **Ignore** doesn't add the error + message to the `$Error` automatic variable. The **Ignore** value is also + valid for `$ErrorActionPreference`, where it suppresses both non-terminating + and statement-terminating errors. However, **Ignore** only prevents `$Error` + recording for non-terminating errors. Terminating errors that are suppressed + by `Ignore` are still recorded in `$Error`. - **Inquire**: Displays the error message and asks you whether you want to continue. - **SilentlyContinue**: No effect. The error message isn't displayed and execution continues without interruption. - **Stop**: Displays the error message and stops executing. In addition to the - error generated, the **Stop** value generates an ActionPreferenceStopException - object to the error stream. + error generated, the **Stop** value generates an + ActionPreferenceStopException object to the error stream. - **Suspend**: Automatically suspends a workflow job to allow for further investigation. After investigation, the workflow can be resumed. The **Suspend** value is intended for per-command use, not for use as saved preference. **Suspend** isn't a valid value for the `$ErrorActionPreference` variable. -`$ErrorActionPreference` and the **ErrorAction** parameter don't affect how -PowerShell responds to terminating errors that stop cmdlet processing. For more -information about the **ErrorAction** common parameter, see +`$ErrorActionPreference` applies to **both** non-terminating and +statement-terminating errors. Unlike the `-ErrorAction` parameter (which only +affects non-terminating errors), the preference variable can also suppress or +escalate errors generated by `$PSCmdlet.ThrowTerminatingError()`. When set to +**Stop**, it escalates non-terminating errors to script-terminating errors. For +more information about error categories, see [about_Error_Handling][67]. For +more information about the **ErrorAction** common parameter, see [about_CommonParameters][29]. +Many native commands write to `stderr` as an alternative stream for additional +information. This behavior can cause confusion when looking through errors or +the additional output information can be lost to the user if +`$ErrorActionPreference` is set to a state that mutes the output. + ### Examples These examples show the effect of the different values of the @@ -1775,3 +1788,4 @@ At line:1 char:1 [63]: xref:System.Text.UTF7Encoding [64]: xref:System.Text.UTF8Encoding [65]: about_Functions_CmdletBindingAttribute.md +[67]: about_Error_Handling.md diff --git a/reference/5.1/Microsoft.PowerShell.Core/About/about_Throw.md b/reference/5.1/Microsoft.PowerShell.Core/About/about_Throw.md index d4d32399004..1d4f9c9a6bb 100644 --- a/reference/5.1/Microsoft.PowerShell.Core/About/about_Throw.md +++ b/reference/5.1/Microsoft.PowerShell.Core/About/about_Throw.md @@ -1,7 +1,7 @@ --- -description: Describes the `throw` keyword, which generates a terminating error. +description: Describes the `throw` keyword, which generates a script-terminating error by default. Locale: en-US -ms.date: 01/18/2026 +ms.date: 04/02/2026 online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_throw?view=powershell-5.1&WT.mc_id=ps-gethelp schema: 2.0.0 title: about_Throw @@ -10,12 +10,30 @@ title: about_Throw ## Short description -Describes the `throw` keyword that generates a terminating error. +Describes the `throw` keyword, which generates a script-terminating error by +default. ## Long description -The `throw` keyword causes a terminating error. You can use the `throw` keyword -to stop the processing of a command, function, or script. +The `throw` keyword causes a script-terminating error by default. You can use +the `throw` keyword to stop the processing of a command, function, or script. + +Unlike statement-terminating errors, the `throw` keyword unwinds the entire +call stack. Execution stops completely unless the error is caught by a +`try/catch` block or `trap` statement. + +> [!NOTE] +> `$ErrorActionPreference` can suppress `throw`. When set to `SilentlyContinue` +> or `Ignore`, the error doesn't propagate and execution continues at the next +> statement. When calling an advanced function with +> `-ErrorAction SilentlyContinue`, the parameter translates to a scope-local +> `$ErrorActionPreference` value, so it also suppresses `throw` inside that +> function. Even when suppressed, `throw` still records an entry in `$Error`. +> The `Ignore` value only prevents `$Error` recording for non-terminating +> errors like those generated by `$PSCmdlet.ThrowTerminatingError()`. + +For more information about error categories and `$ErrorActionPreference` +behavior, see [about_Error_Handling][03]. For example, you can use the `throw` keyword in the statement block of an `if` statement to respond to a condition or in the `catch` block of a @@ -50,7 +68,7 @@ At line:1 char:6 If the `throw` keyword is used in a `catch` block without an expression, it throws the current RuntimeException again. For more information, see -[about_Try_Catch_Finally](about_Try_Catch_Finally.md). +[about_Try_Catch_Finally][07]. ## Throwing a string @@ -133,13 +151,23 @@ object is automatically saved in the `$Error` automatic variable. Unlike past versions of PowerShell, don't use the `throw` keyword for parameter validation. See -[about_Functions_Advanced_Parameters](about_Functions_Advanced_Parameters.md) +[about_Functions_Advanced_Parameters][04] for the correct way. ## See also -- [about_Break](about_Break.md) -- [about_Continue](about_Continue.md) -- [about_Scopes](about_Scopes.md) -- [about_Trap](about_Trap.md) -- [about_Try_Catch_Finally](about_Try_Catch_Finally.md) +- [about_Break][01] +- [about_Continue][02] +- [about_Error_Handling][03] +- [about_Scopes][05] +- [about_Trap][06] +- [about_Try_Catch_Finally][07] + + +[01]: about_Break.md +[02]: about_Continue.md +[03]: about_Error_Handling.md +[04]: about_Functions_Advanced_Parameters.md +[05]: about_Scopes.md +[06]: about_Trap.md +[07]: about_Try_Catch_Finally.md diff --git a/reference/5.1/Microsoft.PowerShell.Core/About/about_Trap.md b/reference/5.1/Microsoft.PowerShell.Core/About/about_Trap.md index f560fc5b38a..d5f4a0e459b 100644 --- a/reference/5.1/Microsoft.PowerShell.Core/About/about_Trap.md +++ b/reference/5.1/Microsoft.PowerShell.Core/About/about_Trap.md @@ -1,7 +1,7 @@ --- -description: Describes a keyword that handles a terminating error. +description: Describes a keyword that handles statement-terminating and script-terminating errors. Locale: en-US -ms.date: 01/13/2026 +ms.date: 04/02/2026 online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_trap?view=powershell-5.1&WT.mc_id=ps-gethelp schema: 2.0.0 title: about_Trap @@ -10,14 +10,16 @@ title: about_Trap ## Short description -Describes a keyword that handles a terminating error. +Describes a keyword that handles statement-terminating and script-terminating +errors. ## Long description -A terminating error stops a statement from running. If PowerShell doesn't -handle a terminating error in some way, PowerShell also stops running the -function or script in the current pipeline. In other languages, such as C#, -terminating errors are known as exceptions. +A terminating error stops a statement from running. PowerShell distinguishes +_statement-terminating_ errors (which stop only the current statement) from +_script-terminating_ errors (which unwind the entire call stack). The `trap` +keyword can handle both kinds. For more information about error categories, see +[about_Error_Handling][07]. The `trap` keyword specifies a list of statements to run when a terminating error occurs. `trap` statements can handle the terminating errors in the @@ -488,8 +490,18 @@ statement. For more information, see ## See also -- [about_Break](about_Break.md) -- [about_Continue](about_Continue.md) -- [about_Scopes](about_Scopes.md) -- [about_Throw](about_Throw.md) -- [about_Try_Catch_Finally](about_Try_Catch_Finally.md) +- [about_Break][01] +- [about_Continue][02] +- [about_Error_Handling][07] +- [about_Scopes][03] +- [about_Throw][04] +- [about_Try_Catch_Finally][05] + + +[01]: about_Break.md +[02]: about_Continue.md +[03]: about_Scopes.md +[04]: about_Throw.md +[05]: about_Try_Catch_Finally.md +[06]: https://wikipedia.org/wiki/JavaScript_syntax#hoisting +[07]: about_Error_Handling.md diff --git a/reference/5.1/Microsoft.PowerShell.Core/About/about_Try_Catch_Finally.md b/reference/5.1/Microsoft.PowerShell.Core/About/about_Try_Catch_Finally.md index 95009158ef9..168d73a7601 100644 --- a/reference/5.1/Microsoft.PowerShell.Core/About/about_Try_Catch_Finally.md +++ b/reference/5.1/Microsoft.PowerShell.Core/About/about_Try_Catch_Finally.md @@ -1,7 +1,7 @@ --- -description: Describes how to use the `try`, `catch`, and `finally` blocks to handle terminating errors. +description: Describes how to use the `try`, `catch`, and `finally` blocks to handle statement-terminating and script-terminating errors. Locale: en-US -ms.date: 01/13/2026 +ms.date: 04/02/2026 online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_try_catch_finally?view=powershell-5.1&WT.mc_id=ps-gethelp schema: 2.0.0 title: about_Try_Catch_Finally @@ -11,18 +11,31 @@ title: about_Try_Catch_Finally ## Short description Describes how to use the `try`, `catch`, and `finally` blocks to handle -terminating errors. +statement-terminating and script-terminating errors. ## Long description Use `try`, `catch`, and `finally` blocks to respond to or handle terminating -errors in scripts. The `trap` statement can also be used to handle terminating -errors in scripts. For more information, see [about_Trap][05]. +errors in scripts. PowerShell has two kinds of terminating errors: -A terminating error stops a statement from running. If PowerShell does not -handle a terminating error in some way, PowerShell also stops running the -function or script using the current pipeline. In other languages, such as C\#, -terminating errors are referred to as exceptions. +- _statement-terminating_ errors that stop the current statement and +- _script-terminating_ errors that unwind the entire call stack + +Both kinds are caught by `try/catch`. You can also use the `trap` statement to +handle terminating errors. For more information, see [about_Trap][05]. For a +comprehensive overview of all error types, see [about_Error_Handling][06]. + +A statement-terminating error stops the current statement from running, but +PowerShell continues at the next statement unless the error is also +script-terminating. A script-terminating error (such as an error produced by +the `throw` keyword) stops the entire script unless caught by a `try/catch` +block or `trap` statement. + +> [!NOTE] +> `$ErrorActionPreference` can suppress `throw`. When set to `SilentlyContinue` +> or `Ignore`, the error doesn't propagate and execution continues at the next +> statement. For details, see the _Script-terminating errors_ section of +> [about_Error_Handling][07]. Use the `try` block to define a section of a script in which you want PowerShell to monitor for errors. When an error occurs within the `try` block, @@ -255,7 +268,7 @@ try { "An error occurred that could not be resolved." } finally { $wc.Dispose() - if (Test-Path $tempPath) { Remove-Item $tempFile } + if (Test-Path $tempFile) { Remove-Item $tempFile } } ``` @@ -263,6 +276,7 @@ try { - [about_Break][01] - [about_Continue][02] +- [about_Error_Handling][06] - [about_Scopes][03] - [about_Throw][04] - [about_Trap][05] @@ -273,3 +287,5 @@ try { [03]: about_Scopes.md [04]: about_Throw.md [05]: about_Trap.md +[06]: about_Error_Handling.md +[07]: about_Error_Handling.md#script-terminating-errors diff --git a/reference/7.4/Microsoft.PowerShell.Core/About/about_Automatic_Variables.md b/reference/7.4/Microsoft.PowerShell.Core/About/about_Automatic_Variables.md index 55b127c6ff4..4e1ee08bf07 100644 --- a/reference/7.4/Microsoft.PowerShell.Core/About/about_Automatic_Variables.md +++ b/reference/7.4/Microsoft.PowerShell.Core/About/about_Automatic_Variables.md @@ -1,7 +1,7 @@ --- description: Describes variables that store state information for PowerShell. These variables are created and maintained by PowerShell. Locale: en-US -ms.date: 02/10/2026 +ms.date: 04/02/2026 no-loc: [Reset, Current, Background, Blink, Bold, Foreground, Formatting, Hidden, Italic, Reset, Reverse, Underline, PSEventArgs, PSEventSubscriber, PSEdition] online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_automatic_variables?view=powershell-5.1&WT.mc_id=ps-gethelp schema: 2.0.0 @@ -167,8 +167,8 @@ Contains a list of names of the experimental features that are enabled. Contains an array of error objects that represent the most recent errors. The most recent error is the first error object in the array `$Error[0]`. -To prevent an error from being added to the `$Error` array, use the -**ErrorAction** common parameter with a value of **Ignore**. For more +To prevent a non-terminating error from being added to the `$Error` array, use +the **ErrorAction** common parameter with a value of **Ignore**. For more information, see [about_CommonParameters][53]. ### `$Event` diff --git a/reference/7.4/Microsoft.PowerShell.Core/About/about_CommonParameters.md b/reference/7.4/Microsoft.PowerShell.Core/About/about_CommonParameters.md index fa55178e6cd..5893ac23cf3 100644 --- a/reference/7.4/Microsoft.PowerShell.Core/About/about_CommonParameters.md +++ b/reference/7.4/Microsoft.PowerShell.Core/About/about_CommonParameters.md @@ -1,7 +1,7 @@ --- description: Describes the parameters that can be used with any cmdlet. Locale: en-US -ms.date: 01/18/2026 +ms.date: 04/02/2026 no-loc: [Confirm, Debug, ErrorAction, ErrorVariable, InformationAction, InformationVariable, OutBuffer, OutVariable, PipelineVariable, ProgressAction, Verbose, WarningAction, WarningVariable, WhatIf] online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_commonparameters?view=powershell-5.1&WT.mc_id=ps-gethelp schema: 2.0.0 @@ -105,8 +105,8 @@ the display of debugging messages when `$DebugPreference` isn't ### -ErrorAction Determines how the cmdlet responds to a non-terminating error from the command. -This parameter works only when the command generates a non-terminating error, -such as those from the `Write-Error` cmdlet. +This parameter overrides the value of the `$ErrorActionPreference` variable for +non-terminating errors generated by the command or the `Write-Error` cmdlet. ```yaml Type: ActionPreference @@ -124,22 +124,28 @@ variable for the current command. Because the default value of the `$ErrorActionPreference` variable is `Continue`, error messages are displayed and execution continues unless you use the `ErrorAction` parameter. -The `ErrorAction` parameter has no effect on terminating errors (such as -missing data, parameters that aren't valid, or insufficient permissions) that -prevent a command from completing successfully. +The `-ErrorAction` parameter doesn't prevent statement-terminating errors +(such as missing data, parameters that aren't valid, or insufficient +permissions) from stopping the current statement. However, when set to `Stop`, +it escalates non-terminating errors to script-terminating errors, making them +catchable by `try/catch`. For more information about error categories, see +[about_Error_Handling][15]. - `Break` Enters the debugger when an error occurs or an exception is raised. - `Continue` displays the error message and continues executing the command. `Continue` is the default. - `Ignore` suppresses the error message and continues executing the command. - Unlike `SilentlyContinue`, `Ignore` doesn't add the error message to the - `$Error` automatic variable. The `Ignore` value is introduced in PowerShell - 3.0. + Unlike `SilentlyContinue`, `Ignore` doesn't add the non-terminating error to + the `$Error` automatic variable. The `Ignore` value is introduced in + PowerShell 3.0. - `Inquire` displays the error message and prompts you for confirmation before continuing execution. This value is rarely used. - `SilentlyContinue` suppresses the error message and continues executing the command. -- `Stop` displays the error message and stops executing the command. +- `Stop` displays the error message and stops executing the command. The + `Stop` value escalates the non-terminating error to a terminating error + by generating an `ActionPreferenceStopException`. The error can then + be caught by a `try/catch` block or `trap` statement. - `Suspend` is only available for workflows which aren't supported in PowerShell 6 and beyond. diff --git a/reference/7.4/Microsoft.PowerShell.Core/About/about_Error_Handling.md b/reference/7.4/Microsoft.PowerShell.Core/About/about_Error_Handling.md new file mode 100644 index 00000000000..a6b16ff5567 --- /dev/null +++ b/reference/7.4/Microsoft.PowerShell.Core/About/about_Error_Handling.md @@ -0,0 +1,562 @@ +--- +description: Describes the types of errors in PowerShell and the mechanisms for handling them. +Locale: en-US +ms.date: 03/26/2026 +online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_error_handling?view=powershell-7.4&WT.mc_id=ps-gethelp +schema: 2.0.0 +title: about_Error_Handling +--- +# about_Error_Handling + +## Short description + +Describes the types of errors in PowerShell and the mechanisms for handling +them. + +## Long description + +PowerShell distinguishes three categories of errors: + +- Non-terminating errors +- Statement-terminating errors +- Script-terminating errors + +Understanding the distinction is essential for writing reliable scripts and +modules, because each category has different default behavior and requires +different handling techniques. + +Additionally, external (native) programs report failure through exit codes, +which PowerShell tracks separately from its own error system. + +## Types of errors + +### Non-terminating errors + +A non-terminating error reports a problem but doesn't stop the pipeline. The +command continues processing subsequent input objects. Non-terminating errors +are generated by: + +- The `Write-Error` cmdlet +- The `$PSCmdlet.WriteError()` method in advanced functions +- Cmdlets that encounter recoverable failures on individual input objects + +By default, PowerShell displays the error message and continues execution. + +```powershell +# Non-terminating error: the pipeline continues after the failure +'file1.txt', 'noSuchFile.txt', 'file3.txt' | ForEach-Object { + Get-Content $_ -ErrorAction Continue +} +``` + +In this example, `Get-Content` reports a non-terminating error for +`noSuchFile.txt` and then continues processing `file3.txt`. + +Non-terminating errors do **not** trigger `catch` or `trap` by default. + +### Statement-terminating errors + +A statement-terminating error stops the current statement (pipeline) from +running, but execution continues at the next statement in the script. +Statement-terminating errors are generated by: + +- The `$PSCmdlet.ThrowTerminatingError()` method in advanced functions and + compiled cmdlets +- Engine errors such as `CommandNotFoundException` (calling a command that + doesn't exist) and `ParameterBindingException` (invalid parameter arguments) +- .NET method calls that throw exceptions, such as `[int]::Parse('abc')` + +```powershell +# Statement-terminating error: Get-Item fails, but the next statement runs +Get-Item -Path 'C:\NoSuchFile.txt' +Write-Output 'This still runs' +``` + +Statement-terminating errors can be caught by `try/catch` and `trap`. + +> [!NOTE] +> `.ThrowTerminatingError()` doesn't consult the `-ErrorAction` parameter +> (except for the `Break` value, which enters the debugger). However, +> `$ErrorActionPreference` _does_ apply to statement-terminating errors +> through the engine's statement-level handler. For example, +> `$ErrorActionPreference = 'SilentlyContinue'` can suppress a +> statement-terminating error so that the script continues at the next +> statement. The `-ErrorAction` parameter can't do this. For details, see +> [The $ErrorActionPreference asymmetry][05]. + +### Script-terminating errors + +A script-terminating error unwinds the entire call stack. Execution stops +completely unless the error is caught by a `try/catch` block or `trap` +statement. Script-terminating errors are generated by: + +- The `throw` keyword +- Parse errors (syntax errors that prevent the script from being compiled) +- Non-terminating errors **escalated** by `-ErrorAction Stop` or + `$ErrorActionPreference = 'Stop'` in non-advanced contexts. For more + information, see [How escalation works][01]. +- Certain critical engine failures + +```powershell +# Script-terminating error: throw unwinds the call stack +function Test-Throw { + throw 'Critical failure' + Write-Output 'This never runs' +} + +Test-Throw +Write-Output 'This never runs either (unless caught)' +``` + +The `throw` keyword generates a script-terminating error by default. However, +`$ErrorActionPreference` _can_ suppress `throw` when set to `SilentlyContinue` +or `Ignore`. When calling an advanced function with +`-ErrorAction SilentlyContinue`, the parameter translates to a scope-local +`$ErrorActionPreference` value, so it also suppresses `throw` inside that +function. + +> [!NOTE] +> Even with `$ErrorActionPreference = 'Ignore'`, a `throw` that's suppressed +> still records an entry in `$Error`. The `Ignore` value only prevents `$Error` +> recording for **non-terminating** errors. + +> [!IMPORTANT] +> The terms _statement-terminating_ and _script-terminating_ describe the scope +> of impact, not the severity of the error. A statement-terminating error stops +> one statement. A script-terminating error stops the entire script and its +> callers. Both can be caught by `try/catch`. + +### External program errors + +External (native) programs don't participate in PowerShell's error system +directly. They report failure through a non-zero exit code, which PowerShell +stores in the `$LASTEXITCODE` automatic variable. + +```powershell +git clone https://example.com/nonexistent.git 2>$null +if ($LASTEXITCODE -ne 0) { + Write-Error "git failed with exit code $LASTEXITCODE" +} +``` + +By default, a non-zero exit code from a native program: + +- Sets `$?` to `$false` +- Does **not** generate an `ErrorRecord` in `$Error` +- Does **not** trigger `catch` or `trap` + +PowerShell 7.3 added the experimental preference variable +`$PSNativeCommandUseErrorActionPreference`, which became a stable feature in +7.4. When you set this variable to `$true`, it causes a non-zero exit code to +emit a **non-terminating error** whose message states the specific exit code (a +`NativeCommandExitException`). This error respects `$ErrorActionPreference`, so +setting it to `Stop` promotes the error to a script-terminating error that can +be caught with `try`/`catch`. + +## Error state variables + +PowerShell maintains several automatic variables that reflect the current error +state. + +### `$?` + +Contains `$true` if the last operation succeeded and `$false` if it produced +any error (non-terminating or terminating). For native commands, `$?` is set +based on the exit code: `$true` for exit code `0`, `$false` otherwise. + +```powershell +Get-Item -Path 'C:\NoSuchFile.txt' 2>$null +$? # False +``` + +### `$Error` + +An `ArrayList` that stores the most recent error records, with the most recent +error at index `0`. The list holds up to `$MaximumErrorCount` entries (default +256). + +All terminating errors are added to `$Error`. For terminating errors, `Ignore` +suppresses display but still records the error in `$Error`. All non-terminating +are added to `$Error` unless `-ErrorAction Ignore` is used on non-terminating +errors, which prevents both display and recording. + +### `$LASTEXITCODE` + +Contains the exit code of the last native program that ran. A value of `0` +conventionally indicates success. Any non-zero value indicates failure. This +variable isn't affected by PowerShell cmdlet errors. + +## Control error behavior + +### The `-ErrorAction` common parameter + +The `-ErrorAction` common parameter overrides `$ErrorActionPreference` for a +single command. It controls how PowerShell responds to **non-terminating** +errors from that command. + +| Value | Behavior | +| ------------------ | -------------------------------------------------------------------- | +| `Continue` | Display the error and continue (default) | +| `SilentlyContinue` | Suppress display, add to `$Error`, continue | +| `Ignore` | Suppress display and don't add to `$Error` | +| `Stop` | **Escalate** to a terminating error (see [How escalation works][01]) | +| `Inquire` | Prompt the user for a decision | +| `Break` | Enter the debugger | + +`-ErrorAction` doesn't change the behavior of errors generated by +`$PSCmdlet.ThrowTerminatingError()`. Those errors are always +statement-terminating regardless of the caller's preference. + +### The `$ErrorActionPreference `variable + +The `$ErrorActionPreference` preference variable applies to all commands in the +current scope and child scopes. It accepts the same values as `-ErrorAction`. + +```powershell +$ErrorActionPreference = 'Stop' +# All non-terminating errors in this scope now become terminating +Write-Error 'This now throws' # Generates ActionPreferenceStopException +``` + +When `-ErrorAction` is specified on a command, it takes precedence over +`$ErrorActionPreference` for that command. + +### How escalation works + +When `-ErrorAction Stop` or `$ErrorActionPreference = 'Stop'` is in effect, +PowerShell converts non-terminating errors into terminating errors using the +following mechanism: + +1. A cmdlet calls `WriteError()` internally to emit a non-terminating error. +1. The engine checks the effective `ErrorAction` preference for the command. +1. Because the preference is `Stop`, the engine creates an + `ActionPreferenceStopException` that wraps the original error record. +1. If caught by `catch`, the original error information is accessible through + `$_.Exception.ErrorRecord`. + +The scope of the escalated error depends on context: + +- In **non-advanced** scripts, functions, or script blocks, setting + `$ErrorActionPreference = 'Stop'` escalates to a **script-terminating** + error. The error propagates up the call stack. +- In **advanced** functions and script blocks (those with `[CmdletBinding()]`), + the error remains **statement-terminating**. Execution continues at the next + statement after the call. +- Passing `-ErrorAction Stop` to an advanced function has the same effect as + setting `$ErrorActionPreference = 'Stop'` inside it, because `-ErrorAction` + translates to a scope-local `$ErrorActionPreference` value. + +### Escalation examples + +- NON-advanced: script-terminating ('after' does NOT print) + + ```powershell + & { + param() + $ErrorActionPreference = 'Stop' + Get-Item 'NoSuchPath' + } 2>$null + 'after' + ``` + +- ADVANCED: statement-terminating ('after' DOES print) + + ```powershell + & { + [CmdletBinding()] + param() + $ErrorActionPreference = 'Stop'; Get-Item 'NoSuchPath' + } 2>$null + 'after' + ``` + +- Without `-ErrorAction Stop`: non-terminating, catch doesn't run + + ```powershell + try { + Write-Error 'This is non-terminating' + Write-Output 'Execution continues' + } catch { + Write-Output "Caught: $_" # Not reached + } + ``` + +- With `-ErrorAction Stop`: escalated to terminating + + ```powershell + try { + Write-Error 'This becomes terminating' -ErrorAction Stop + } catch { + Write-Output "Caught: $_" # Reached + } + ``` + +Escalated errors can be caught by their original exception type. The engine +unwraps the `ActionPreferenceStopException` to find the underlying exception: + +```powershell +try { + Get-Item -Path 'C:\NoSuchFile.txt' -ErrorAction Stop +} catch [System.Management.Automation.ItemNotFoundException] { + Write-Output "File not found: $($_.Exception.Message)" +} +``` + +### The `$ErrorActionPreference` asymmetry + +The `-ErrorAction` parameter and the `$ErrorActionPreference` variable behave +differently with terminating errors. It's important to understand this +asymmetry: + +- `-ErrorAction` only affects **non-terminating** errors. When a cmdlet calls + `$PSCmdlet.ThrowTerminatingError()`, the `-ErrorAction` parameter is ignored + (except for `Break`, which enters the debugger). The error is always thrown. + +- `$ErrorActionPreference` affects **both** non-terminating and + statement-terminating errors. The engine's statement-level error handler + reads `$ErrorActionPreference` (not the `-ErrorAction` parameter) and can + suppress a statement-terminating error when the value is `SilentlyContinue` + or `Ignore`. + +```powershell +function Test-Asymmetry { + [CmdletBinding()] + param() + $er = [System.Management.Automation.ErrorRecord]::new( + [System.InvalidOperationException]::new('test error'), + 'TestError', + [System.Management.Automation.ErrorCategory]::InvalidOperation, + $null + ) + $PSCmdlet.ThrowTerminatingError($er) +} + +# -ErrorAction SilentlyContinue does NOT suppress the error: +Test-Asymmetry -ErrorAction SilentlyContinue # Error is still thrown + +# $ErrorActionPreference DOES suppress the error: +$ErrorActionPreference = 'SilentlyContinue' +Test-Asymmetry # Error is silently suppressed, script continues +$ErrorActionPreference = 'Continue' +``` + +> [!IMPORTANT] +> `$ErrorActionPreference` can't suppress errors that have +> `SuppressPromptInInterpreter` set to `true`. These always propagate +> regardless of the preference variable. Examples of this type of error +> include: +> +> - `ActionPreferenceStopException` from `-ErrorAction Stop` escalation +> - Errors inside PowerShell class methods +> - `PipelineStoppedException` + +## Handle errors + +### `try/catch/finally` + +Use `try/catch/finally` to handle statement-terminating and script-terminating +errors. When an error occurs inside a `try` block, PowerShell searches for a +matching `catch` block. The `finally` block always runs, whether or not an +error occurred. + +```powershell +try { + $result = Get-Content -Path 'data.txt' -ErrorAction Stop +} +catch [System.Management.Automation.ItemNotFoundException] { + Write-Warning 'Data file not found, using defaults.' + $result = 'default' +} +catch { + Write-Warning "Unexpected error: $_" +} +finally { + Write-Verbose 'Cleanup complete.' -Verbose +} +``` + +Inside a `try` block, the engine sets an internal flag that causes non- +terminating errors escalated by `-ErrorAction Stop` or +`$ErrorActionPreference = 'Stop'` to propagate to the `catch` block. This +is designed behavior, not a special case. + +For full syntax details, see [about_Try_Catch_Finally][12]. + +### `trap` + +The `trap` statement handles terminating errors at the scope level. When an +error occurs anywhere in the enclosing scope, the `trap` block runs. + +- **Default** (no `break` or `continue`): The error is displayed and execution + continues at the next statement after the one that caused the error. +- **`continue`** in the trap: Suppresses the error message and resumes at the + next statement. +- **`break`** in the trap: The error propagates to the parent scope. + +```powershell +trap [System.Management.Automation.CommandNotFoundException] { + Write-Warning "Command not found: $($_.TargetObject)" + continue +} + +NonsenseCommand # Trap fires, execution continues +Write-Output 'This runs because the trap used continue' +``` + +For full syntax details, see [about_Trap][11]. + +## Reporting errors in functions and scripts + +When writing functions and scripts, choose the error-reporting mechanism that +matches the severity of the failure. + +### Non-terminating - use `Write-Error` + +Use `Write-Error` when the function can continue processing other input. This +is appropriate for pipeline functions that process multiple objects and +encounter failures on individual items. + +```powershell +function Test-Path-Safe { + [CmdletBinding()] + param([Parameter(ValueFromPipeline)][string]$Path) + process { + if (-not (Test-Path $Path)) { + Write-Error "Path not found: $Path" + return + } + $Path + } +} +``` + +> [!NOTE] +> In advanced functions (those with `[CmdletBinding()]`), use +> `$PSCmdlet.WriteError()` instead of `Write-Error` to ensure that `$?` is +> properly set to `$false` in the caller's scope. The `Write-Error` cmdlet +> doesn't always set `$?` correctly. + +### Statement-terminating - use `$PSCmdlet.ThrowTerminatingError()` + +Use `$PSCmdlet.ThrowTerminatingError()` when the function can't continue at all +but the caller should decide how to handle the failure. This is the recommended +approach in advanced functions. + +```powershell +function Get-Config { + [CmdletBinding()] + param([string]$Path) + + if (-not (Test-Path $Path)) { + $er = [System.Management.Automation.ErrorRecord]::new( + [System.IO.FileNotFoundException]::new("Config file not found: $Path"), + 'ConfigNotFound', + [System.Management.Automation.ErrorCategory]::ObjectNotFound, + $Path + ) + $PSCmdlet.ThrowTerminatingError($er) + } + + Get-Content $Path | ConvertFrom-Json +} +``` + +After the error leaves the function, the caller treats it as a non-terminating +error by default. The caller can escalate it with `-ErrorAction Stop`. + +### Script-terminating - use `throw` + +Use `throw` when recovery isn't possible and the entire script should stop. + +```powershell +$config = Get-Content 'config.json' -ErrorAction SilentlyContinue | + ConvertFrom-Json + +if (-not $config) { + throw 'Cannot proceed without a valid configuration file.' +} +``` + +### Which mechanism to use + +- When processing multiple inputs where some may fail, use `Write-Error` or + `$PSCmdlet.WriteError()`. +- If the function can't continue, use `$PSCmdlet.ThrowTerminatingError()` and + let the caller decide how to handle it. +- If the entire script must stop immediately, use `throw`. + +## Summary of error types + +The following tables summarize the properties and behaviors of the different +error types in PowerShell. + +### Non-terminating error + +[Non-terminating errors][02] can be generated by `Write-Error` or +`$PSCmdlet.WriteError()`. + +| Attribute | Description | +| ------------------------------------ | ------------------------------- | +| Scope of impact | Pipeline continues | +| Caught by `catch` | No (unless escalated) | +| Caught by `trap` | No (unless escalated) | +| Added to `$Error` | Yes (unless `Ignore`) | +| Sets `$?` to `$false` | Yes | +| Affected by `-ErrorAction` | Yes | +| Affected by `$ErrorActionPreference` | Yes | + +### Statement-terminating error + +[Statement-terminating errors][04] can be generated by +`ThrowTerminatingError()`, engine errors, .NET method exceptions, or +`-ErrorAction Stop` in advanced contexts. + +| Attribute | Description | +| ------------------------------------ | ----------------------------------------- | +| Scope of impact | Current statement stops; script continues | +| Caught by `catch` | Yes | +| Caught by `trap` | Yes | +| Added to `$Error` | Yes | +| Sets `$?` to `$false` | Yes | +| Affected by `-ErrorAction` | No (`Break` only) | +| Affected by `$ErrorActionPreference` | Yes (can suppress) | + +### Script-terminating error + +[Script-terminating errors][03] can be generated by `throw`, parse errors, or +`-ErrorAction Stop` in non-advanced contexts. + +| Attribute | Description | +| ------------------------------------ | ----------------------------- | +| Scope of impact | Call stack unwinds | +| Caught by `catch` | Yes | +| Caught by `trap` | Yes | +| Added to `$Error` | Yes | +| Sets `$?` to `$false` | Yes | +| Affected by `-ErrorAction` | No | +| Affected by `$ErrorActionPreference` | `throw`: Yes (can suppress) | +| Affected by `$ErrorActionPreference` | Escalated: depends on context | + +## See also + +- [about_Automatic_Variables][06] +- [about_CommonParameters][07] +- [about_Preference_Variables][09] +- [about_Output_Streams][08] +- [about_Throw][10] +- [about_Trap][11] +- [about_Try_Catch_Finally][12] + + +[01]: #how-escalation-works +[02]: #non-terminating-errors +[03]: #script-terminating-errors +[04]: #statement-terminating-errors +[05]: #the-erroractionpreference-asymmetry +[06]: about_Automatic_Variables.md +[07]: about_CommonParameters.md +[08]: about_Output_Streams.md +[09]: about_Preference_Variables.md +[10]: about_Throw.md +[11]: about_Trap.md +[12]: about_Try_Catch_Finally.md diff --git a/reference/7.4/Microsoft.PowerShell.Core/About/about_Preference_Variables.md b/reference/7.4/Microsoft.PowerShell.Core/About/about_Preference_Variables.md index 45e84f87bc0..686bf06c180 100644 --- a/reference/7.4/Microsoft.PowerShell.Core/About/about_Preference_Variables.md +++ b/reference/7.4/Microsoft.PowerShell.Core/About/about_Preference_Variables.md @@ -1,7 +1,7 @@ --- description: Variables that customize the behavior of PowerShell. Locale: en-US -ms.date: 12/01/2025 +ms.date: 04/02/2026 online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_preference_variables?view=powershell-7.4&WT.mc_id=ps-gethelp schema: 2.0.0 title: about_Preference_Variables @@ -388,25 +388,32 @@ The valid values are as follows: raised. - **Continue**: (Default) Displays the error message and continues executing. - **Ignore**: Suppresses the error message and continues to execute the - command. The **Ignore** value is intended for per-command use, not for use as - saved preference. **Ignore** isn't a valid value for the - `$ErrorActionPreference` variable. + command. Unlike **SilentlyContinue**, **Ignore** doesn't add the error + message to the `$Error` automatic variable. The **Ignore** value is also + valid for `$ErrorActionPreference`, where it suppresses both non-terminating + and statement-terminating errors. However, **Ignore** only prevents `$Error` + recording for non-terminating errors. Terminating errors that are suppressed + by `Ignore` are still recorded in `$Error`. - **Inquire**: Displays the error message and asks you whether you want to continue. - **SilentlyContinue**: No effect. The error message isn't displayed and execution continues without interruption. - **Stop**: Displays the error message and stops executing. In addition to the - error generated, the **Stop** value generates an ActionPreferenceStopException - object to the error stream. + error generated, the **Stop** value generates an + ActionPreferenceStopException object to the error stream. - **Suspend**: Automatically suspends a workflow job to allow for further investigation. After investigation, the workflow can be resumed. The **Suspend** value is intended for per-command use, not for use as saved preference. **Suspend** isn't a valid value for the `$ErrorActionPreference` variable. -`$ErrorActionPreference` and the **ErrorAction** parameter don't affect how -PowerShell responds to terminating errors that stop cmdlet processing. For more -information about the **ErrorAction** common parameter, see +`$ErrorActionPreference` applies to **both** non-terminating and +statement-terminating errors. Unlike the `-ErrorAction` parameter (which only +affects non-terminating errors), the preference variable can also suppress or +escalate errors generated by `$PSCmdlet.ThrowTerminatingError()`. When set to +**Stop**, it escalates non-terminating errors to script-terminating errors. For +more information about error categories, see [about_Error_Handling][67]. For +more information about the **ErrorAction** common parameter, see [about_CommonParameters][29]. Many native commands write to `stderr` as an alternative stream for additional @@ -419,10 +426,9 @@ like when using redirection operators (`2>&1`), aren't written to the `$Error` variable and the preference variable `$ErrorActionPreference` doesn't affect the redirected output. -PowerShell 7.3 added an experimental feature that allows you to control how -messages written to `stderr` are handled. - -For more information see, [$PSNativeCommandUseErrorActionPreference][18]. +PowerShell 7.4 added a feature that allows you to control how messages written +to `stderr` are handled. For more information, see +[$PSNativeCommandUseErrorActionPreference][18]. ### Examples @@ -1692,6 +1698,7 @@ At line:1 char:1 - [about_Automatic_Variables][28] - [about_CommonParameters][29] - [about_Environment_Variables][30] +- [about_Error_Handling][67] - [about_Profiles][36] - [about_Remote][39] - [about_Scopes][40] @@ -1763,3 +1770,4 @@ At line:1 char:1 [64]: xref:System.Text.UTF7Encoding [65]: xref:System.Text.UTF8Encoding [66]: about_Functions_CmdletBindingAttribute.md +[67]: about_Error_Handling.md diff --git a/reference/7.4/Microsoft.PowerShell.Core/About/about_Throw.md b/reference/7.4/Microsoft.PowerShell.Core/About/about_Throw.md index 5f4d366f72f..3a0b72adb5a 100644 --- a/reference/7.4/Microsoft.PowerShell.Core/About/about_Throw.md +++ b/reference/7.4/Microsoft.PowerShell.Core/About/about_Throw.md @@ -1,7 +1,7 @@ --- -description: Describes the `throw` keyword, which generates a terminating error. +description: Describes the `throw` keyword, which generates a script-terminating error by default. Locale: en-US -ms.date: 01/18/2026 +ms.date: 04/02/2026 online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_throw?view=powershell-7.4&WT.mc_id=ps-gethelp schema: 2.0.0 title: about_Throw @@ -10,12 +10,30 @@ title: about_Throw ## Short description -Describes the `throw` keyword that generates a terminating error. +Describes the `throw` keyword, which generates a script-terminating error by +default. ## Long description -The `throw` keyword causes a terminating error. You can use the `throw` keyword -to stop the processing of a command, function, or script. +The `throw` keyword causes a script-terminating error by default. You can use +the `throw` keyword to stop the processing of a command, function, or script. + +Unlike statement-terminating errors, the `throw` keyword unwinds the entire +call stack. Execution stops completely unless the error is caught by a +`try/catch` block or `trap` statement. + +> [!NOTE] +> `$ErrorActionPreference` can suppress `throw`. When set to `SilentlyContinue` +> or `Ignore`, the error doesn't propagate and execution continues at the next +> statement. When calling an advanced function with +> `-ErrorAction SilentlyContinue`, the parameter translates to a scope-local +> `$ErrorActionPreference` value, so it also suppresses `throw` inside that +> function. Even when suppressed, `throw` still records an entry in `$Error`. +> The `Ignore` value only prevents `$Error` recording for non-terminating +> errors like those generated by `$PSCmdlet.ThrowTerminatingError()`. + +For more information about error categories and `$ErrorActionPreference` +behavior, see [about_Error_Handling][03]. For example, you can use the `throw` keyword in the statement block of an `if` statement to respond to a condition or in the `catch` block of a @@ -46,7 +64,7 @@ Exception: ScriptHalted If the `throw` keyword is used in a `catch` block without an expression, it throws the current RuntimeException again. For more information, see -[about_Try_Catch_Finally](about_Try_Catch_Finally.md). +[about_Try_Catch_Finally][07]. ## Throwing a string @@ -116,13 +134,23 @@ object is automatically saved in the `$Error` automatic variable. Unlike past versions of PowerShell, don't use the `throw` keyword for parameter validation. See -[about_Functions_Advanced_Parameters](about_Functions_Advanced_Parameters.md) +[about_Functions_Advanced_Parameters][04] for the correct way. ## See also -- [about_Break](about_Break.md) -- [about_Continue](about_Continue.md) -- [about_Scopes](about_Scopes.md) -- [about_Trap](about_Trap.md) -- [about_Try_Catch_Finally](about_Try_Catch_Finally.md) +- [about_Break][01] +- [about_Continue][02] +- [about_Error_Handling][03] +- [about_Scopes][05] +- [about_Trap][06] +- [about_Try_Catch_Finally][07] + + +[01]: about_Break.md +[02]: about_Continue.md +[03]: about_Error_Handling.md +[04]: about_Functions_Advanced_Parameters.md +[05]: about_Scopes.md +[06]: about_Trap.md +[07]: about_Try_Catch_Finally.md diff --git a/reference/7.4/Microsoft.PowerShell.Core/About/about_Trap.md b/reference/7.4/Microsoft.PowerShell.Core/About/about_Trap.md index 3867f3b5e57..8ca161ec153 100644 --- a/reference/7.4/Microsoft.PowerShell.Core/About/about_Trap.md +++ b/reference/7.4/Microsoft.PowerShell.Core/About/about_Trap.md @@ -1,7 +1,7 @@ --- -description: Describes a keyword that handles a terminating error. +description: Describes a keyword that handles statement-terminating and script-terminating errors. Locale: en-US -ms.date: 01/13/2026 +ms.date: 04/02/2026 online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_trap?view=powershell-7.4&WT.mc_id=ps-gethelp schema: 2.0.0 title: about_Trap @@ -10,14 +10,16 @@ title: about_Trap ## Short description -Describes a keyword that handles a terminating error. +Describes a keyword that handles statement-terminating and script-terminating +errors. ## Long description -A terminating error stops a statement from running. If PowerShell doesn't -handle a terminating error in some way, PowerShell also stops running the -function or script in the current pipeline. In other languages, such as C#, -terminating errors are known as exceptions. +A terminating error stops a statement from running. PowerShell distinguishes +_statement-terminating_ errors (which stop only the current statement) from +_script-terminating_ errors (which unwind the entire call stack). The `trap` +keyword can handle both kinds. For more information about error categories, see +[about_Error_Handling][07]. The `trap` keyword specifies a list of statements to run when a terminating error occurs. `trap` statements can handle the terminating errors in the @@ -286,7 +288,7 @@ after loop In the output, you can see the loops continue until the last iteration. When the script tries to divide 1 by 0, PowerShell throws a terminating error. The -script skips the rest of the `foreach` statement, runs the `try` statement, +script skips the rest of the `foreach` statement, runs the `trap` statement, and continues after the `foreach` statement. ## Trapping errors and scope @@ -468,6 +470,7 @@ statement. For more information, see - [about_Break][01] - [about_Continue][02] +- [about_Error_Handling][07] - [about_Scopes][03] - [about_Throw][04] - [about_Try_Catch_Finally][05] @@ -479,3 +482,4 @@ statement. For more information, see [04]: about_Throw.md [05]: about_Try_Catch_Finally.md [06]: https://wikipedia.org/wiki/JavaScript_syntax#hoisting +[07]: about_Error_Handling.md diff --git a/reference/7.4/Microsoft.PowerShell.Core/About/about_Try_Catch_Finally.md b/reference/7.4/Microsoft.PowerShell.Core/About/about_Try_Catch_Finally.md index 991e4460fb9..046510b62ac 100644 --- a/reference/7.4/Microsoft.PowerShell.Core/About/about_Try_Catch_Finally.md +++ b/reference/7.4/Microsoft.PowerShell.Core/About/about_Try_Catch_Finally.md @@ -1,7 +1,7 @@ --- -description: Describes how to use the `try`, `catch`, and `finally` blocks to handle terminating errors. +description: Describes how to use the `try`, `catch`, and `finally` blocks to handle statement-terminating and script-terminating errors. Locale: en-US -ms.date: 01/13/2026 +ms.date: 04/02/2026 online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_try_catch_finally?view=powershell-7.4&WT.mc_id=ps-gethelp schema: 2.0.0 title: about_Try_Catch_Finally @@ -11,18 +11,31 @@ title: about_Try_Catch_Finally ## Short description Describes how to use the `try`, `catch`, and `finally` blocks to handle -terminating errors. +statement-terminating and script-terminating errors. ## Long description Use `try`, `catch`, and `finally` blocks to respond to or handle terminating -errors in scripts. The `trap` statement can also be used to handle terminating -errors in scripts. For more information, see [about_Trap][05]. +errors in scripts. PowerShell has two kinds of terminating errors: -A terminating error stops a statement from running. If PowerShell does not -handle a terminating error in some way, PowerShell also stops running the -function or script using the current pipeline. In other languages, such as C\#, -terminating errors are referred to as exceptions. +- _statement-terminating_ errors that stop the current statement and +- _script-terminating_ errors that unwind the entire call stack + +Both kinds are caught by `try/catch`. You can also use the `trap` statement to +handle terminating errors. For more information, see [about_Trap][05]. For a +comprehensive overview of all error types, see [about_Error_Handling][06]. + +A statement-terminating error stops the current statement from running, but +PowerShell continues at the next statement unless the error is also +script-terminating. A script-terminating error (such as an error produced by +the `throw` keyword) stops the entire script unless caught by a `try/catch` +block or `trap` statement. + +> [!NOTE] +> `$ErrorActionPreference` can suppress `throw`. When set to `SilentlyContinue` +> or `Ignore`, the error doesn't propagate and execution continues at the next +> statement. For details, see the _Script-terminating errors_ section of +> [about_Error_Handling][07]. Use the `try` block to define a section of a script in which you want PowerShell to monitor for errors. When an error occurs within the `try` block, @@ -255,7 +268,7 @@ try { "An error occurred that could not be resolved." } finally { $wc.Dispose() - if (Test-Path $tempPath) { Remove-Item $tempFile } + if (Test-Path $tempFile) { Remove-Item $tempFile } } ``` @@ -263,6 +276,7 @@ try { - [about_Break][01] - [about_Continue][02] +- [about_Error_Handling][06] - [about_Scopes][03] - [about_Throw][04] - [about_Trap][05] @@ -273,3 +287,5 @@ try { [03]: about_Scopes.md [04]: about_Throw.md [05]: about_Trap.md +[06]: about_Error_Handling.md +[07]: about_Error_Handling.md#script-terminating-errors diff --git a/reference/7.5/Microsoft.PowerShell.Core/About/about_Automatic_Variables.md b/reference/7.5/Microsoft.PowerShell.Core/About/about_Automatic_Variables.md index 66a95cdeb02..b13dd0cc2c8 100644 --- a/reference/7.5/Microsoft.PowerShell.Core/About/about_Automatic_Variables.md +++ b/reference/7.5/Microsoft.PowerShell.Core/About/about_Automatic_Variables.md @@ -1,7 +1,7 @@ --- description: Describes variables that store state information for PowerShell. These variables are created and maintained by PowerShell. Locale: en-US -ms.date: 02/10/2026 +ms.date: 04/02/2026 no-loc: [Reset, Current, Background, Blink, Bold, Foreground, Formatting, Hidden, Italic, Reset, Reverse, Underline, PSEventArgs, PSEventSubscriber, PSEdition] online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_automatic_variables?view=powershell-7.5&WT.mc_id=ps-gethelp schema: 2.0.0 @@ -167,8 +167,8 @@ Contains a list of names of the experimental features that are enabled. Contains an array of error objects that represent the most recent errors. The most recent error is the first error object in the array `$Error[0]`. -To prevent an error from being added to the `$Error` array, use the -**ErrorAction** common parameter with a value of **Ignore**. For more +To prevent a non-terminating error from being added to the `$Error` array, use +the **ErrorAction** common parameter with a value of **Ignore**. For more information, see [about_CommonParameters][53]. ### `$Event` diff --git a/reference/7.5/Microsoft.PowerShell.Core/About/about_CommonParameters.md b/reference/7.5/Microsoft.PowerShell.Core/About/about_CommonParameters.md index 06cce87a294..705c53b5c3d 100644 --- a/reference/7.5/Microsoft.PowerShell.Core/About/about_CommonParameters.md +++ b/reference/7.5/Microsoft.PowerShell.Core/About/about_CommonParameters.md @@ -1,7 +1,7 @@ --- description: Describes the parameters that can be used with any cmdlet. Locale: en-US -ms.date: 01/18/2026 +ms.date: 04/02/2026 no-loc: [Confirm, Debug, ErrorAction, ErrorVariable, InformationAction, InformationVariable, OutBuffer, OutVariable, PipelineVariable, ProgressAction, Verbose, WarningAction, WarningVariable, WhatIf] online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_commonparameters?view=powershell-7.5&WT.mc_id=ps-gethelp schema: 2.0.0 @@ -105,8 +105,8 @@ the display of debugging messages when `$DebugPreference` isn't ### -ErrorAction Determines how the cmdlet responds to a non-terminating error from the command. -This parameter works only when the command generates a non-terminating error, -such as those from the `Write-Error` cmdlet. +This parameter overrides the value of the `$ErrorActionPreference` variable for +non-terminating errors generated by the command or the `Write-Error` cmdlet. ```yaml Type: ActionPreference @@ -124,22 +124,28 @@ variable for the current command. Because the default value of the `$ErrorActionPreference` variable is `Continue`, error messages are displayed and execution continues unless you use the `ErrorAction` parameter. -The `ErrorAction` parameter has no effect on terminating errors (such as -missing data, parameters that aren't valid, or insufficient permissions) that -prevent a command from completing successfully. +The `-ErrorAction` parameter doesn't prevent statement-terminating errors +(such as missing data, parameters that aren't valid, or insufficient +permissions) from stopping the current statement. However, when set to `Stop`, +it escalates non-terminating errors to script-terminating errors, making them +catchable by `try/catch`. For more information about error categories, see +[about_Error_Handling][15]. - `Break` Enters the debugger when an error occurs or an exception is raised. - `Continue` displays the error message and continues executing the command. `Continue` is the default. - `Ignore` suppresses the error message and continues executing the command. - Unlike `SilentlyContinue`, `Ignore` doesn't add the error message to the - `$Error` automatic variable. The `Ignore` value is introduced in PowerShell - 3.0. + Unlike `SilentlyContinue`, `Ignore` doesn't add the non-terminating error to + the `$Error` automatic variable. The `Ignore` value is introduced in + PowerShell 3.0. - `Inquire` displays the error message and prompts you for confirmation before continuing execution. This value is rarely used. - `SilentlyContinue` suppresses the error message and continues executing the command. -- `Stop` displays the error message and stops executing the command. +- `Stop` displays the error message and stops executing the command. The + `Stop` value escalates the non-terminating error to a terminating error + by generating an `ActionPreferenceStopException`. The error can then + be caught by a `try/catch` block or `trap` statement. - `Suspend` is only available for workflows which aren't supported in PowerShell 6 and beyond. diff --git a/reference/7.5/Microsoft.PowerShell.Core/About/about_Error_Handling.md b/reference/7.5/Microsoft.PowerShell.Core/About/about_Error_Handling.md new file mode 100644 index 00000000000..d39ac3ab850 --- /dev/null +++ b/reference/7.5/Microsoft.PowerShell.Core/About/about_Error_Handling.md @@ -0,0 +1,562 @@ +--- +description: Describes the types of errors in PowerShell and the mechanisms for handling them. +Locale: en-US +ms.date: 03/26/2026 +online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_error_handling?view=powershell-7.5&WT.mc_id=ps-gethelp +schema: 2.0.0 +title: about_Error_Handling +--- +# about_Error_Handling + +## Short description + +Describes the types of errors in PowerShell and the mechanisms for handling +them. + +## Long description + +PowerShell distinguishes three categories of errors: + +- Non-terminating errors +- Statement-terminating errors +- Script-terminating errors + +Understanding the distinction is essential for writing reliable scripts and +modules, because each category has different default behavior and requires +different handling techniques. + +Additionally, external (native) programs report failure through exit codes, +which PowerShell tracks separately from its own error system. + +## Types of errors + +### Non-terminating errors + +A non-terminating error reports a problem but doesn't stop the pipeline. The +command continues processing subsequent input objects. Non-terminating errors +are generated by: + +- The `Write-Error` cmdlet +- The `$PSCmdlet.WriteError()` method in advanced functions +- Cmdlets that encounter recoverable failures on individual input objects + +By default, PowerShell displays the error message and continues execution. + +```powershell +# Non-terminating error: the pipeline continues after the failure +'file1.txt', 'noSuchFile.txt', 'file3.txt' | ForEach-Object { + Get-Content $_ -ErrorAction Continue +} +``` + +In this example, `Get-Content` reports a non-terminating error for +`noSuchFile.txt` and then continues processing `file3.txt`. + +Non-terminating errors do **not** trigger `catch` or `trap` by default. + +### Statement-terminating errors + +A statement-terminating error stops the current statement (pipeline) from +running, but execution continues at the next statement in the script. +Statement-terminating errors are generated by: + +- The `$PSCmdlet.ThrowTerminatingError()` method in advanced functions and + compiled cmdlets +- Engine errors such as `CommandNotFoundException` (calling a command that + doesn't exist) and `ParameterBindingException` (invalid parameter arguments) +- .NET method calls that throw exceptions, such as `[int]::Parse('abc')` + +```powershell +# Statement-terminating error: Get-Item fails, but the next statement runs +Get-Item -Path 'C:\NoSuchFile.txt' +Write-Output 'This still runs' +``` + +Statement-terminating errors can be caught by `try/catch` and `trap`. + +> [!NOTE] +> `.ThrowTerminatingError()` doesn't consult the `-ErrorAction` parameter +> (except for the `Break` value, which enters the debugger). However, +> `$ErrorActionPreference` _does_ apply to statement-terminating errors +> through the engine's statement-level handler. For example, +> `$ErrorActionPreference = 'SilentlyContinue'` can suppress a +> statement-terminating error so that the script continues at the next +> statement. The `-ErrorAction` parameter can't do this. For details, see +> [The $ErrorActionPreference asymmetry][05]. + +### Script-terminating errors + +A script-terminating error unwinds the entire call stack. Execution stops +completely unless the error is caught by a `try/catch` block or `trap` +statement. Script-terminating errors are generated by: + +- The `throw` keyword +- Parse errors (syntax errors that prevent the script from being compiled) +- Non-terminating errors **escalated** by `-ErrorAction Stop` or + `$ErrorActionPreference = 'Stop'` in non-advanced contexts. For more + information, see [How escalation works][01]. +- Certain critical engine failures + +```powershell +# Script-terminating error: throw unwinds the call stack +function Test-Throw { + throw 'Critical failure' + Write-Output 'This never runs' +} + +Test-Throw +Write-Output 'This never runs either (unless caught)' +``` + +The `throw` keyword generates a script-terminating error by default. However, +`$ErrorActionPreference` _can_ suppress `throw` when set to `SilentlyContinue` +or `Ignore`. When calling an advanced function with +`-ErrorAction SilentlyContinue`, the parameter translates to a scope-local +`$ErrorActionPreference` value, so it also suppresses `throw` inside that +function. + +> [!NOTE] +> Even with `$ErrorActionPreference = 'Ignore'`, a `throw` that's suppressed +> still records an entry in `$Error`. The `Ignore` value only prevents `$Error` +> recording for **non-terminating** errors. + +> [!IMPORTANT] +> The terms _statement-terminating_ and _script-terminating_ describe the scope +> of impact, not the severity of the error. A statement-terminating error stops +> one statement. A script-terminating error stops the entire script and its +> callers. Both can be caught by `try/catch`. + +### External program errors + +External (native) programs don't participate in PowerShell's error system +directly. They report failure through a non-zero exit code, which PowerShell +stores in the `$LASTEXITCODE` automatic variable. + +```powershell +git clone https://example.com/nonexistent.git 2>$null +if ($LASTEXITCODE -ne 0) { + Write-Error "git failed with exit code $LASTEXITCODE" +} +``` + +By default, a non-zero exit code from a native program: + +- Sets `$?` to `$false` +- Does **not** generate an `ErrorRecord` in `$Error` +- Does **not** trigger `catch` or `trap` + +PowerShell 7.3 added the experimental preference variable +`$PSNativeCommandUseErrorActionPreference`, which became a stable feature in +7.4. When you set this variable to `$true`, it causes a non-zero exit code to +emit a **non-terminating error** whose message states the specific exit code (a +`NativeCommandExitException`). This error respects `$ErrorActionPreference`, so +setting it to `Stop` promotes the error to a script-terminating error that can +be caught with `try`/`catch`. + +## Error state variables + +PowerShell maintains several automatic variables that reflect the current error +state. + +### `$?` + +Contains `$true` if the last operation succeeded and `$false` if it produced +any error (non-terminating or terminating). For native commands, `$?` is set +based on the exit code: `$true` for exit code `0`, `$false` otherwise. + +```powershell +Get-Item -Path 'C:\NoSuchFile.txt' 2>$null +$? # False +``` + +### `$Error` + +An `ArrayList` that stores the most recent error records, with the most recent +error at index `0`. The list holds up to `$MaximumErrorCount` entries (default +256). + +All terminating errors are added to `$Error`. For terminating errors, `Ignore` +suppresses display but still records the error in `$Error`. All non-terminating +are added to `$Error` unless `-ErrorAction Ignore` is used on non-terminating +errors, which prevents both display and recording. + +### `$LASTEXITCODE` + +Contains the exit code of the last native program that ran. A value of `0` +conventionally indicates success. Any non-zero value indicates failure. This +variable isn't affected by PowerShell cmdlet errors. + +## Control error behavior + +### The `-ErrorAction` common parameter + +The `-ErrorAction` common parameter overrides `$ErrorActionPreference` for a +single command. It controls how PowerShell responds to **non-terminating** +errors from that command. + +| Value | Behavior | +| ------------------ | -------------------------------------------------------------------- | +| `Continue` | Display the error and continue (default) | +| `SilentlyContinue` | Suppress display, add to `$Error`, continue | +| `Ignore` | Suppress display and don't add to `$Error` | +| `Stop` | **Escalate** to a terminating error (see [How escalation works][01]) | +| `Inquire` | Prompt the user for a decision | +| `Break` | Enter the debugger | + +`-ErrorAction` doesn't change the behavior of errors generated by +`$PSCmdlet.ThrowTerminatingError()`. Those errors are always +statement-terminating regardless of the caller's preference. + +### The `$ErrorActionPreference `variable + +The `$ErrorActionPreference` preference variable applies to all commands in the +current scope and child scopes. It accepts the same values as `-ErrorAction`. + +```powershell +$ErrorActionPreference = 'Stop' +# All non-terminating errors in this scope now become terminating +Write-Error 'This now throws' # Generates ActionPreferenceStopException +``` + +When `-ErrorAction` is specified on a command, it takes precedence over +`$ErrorActionPreference` for that command. + +### How escalation works + +When `-ErrorAction Stop` or `$ErrorActionPreference = 'Stop'` is in effect, +PowerShell converts non-terminating errors into terminating errors using the +following mechanism: + +1. A cmdlet calls `WriteError()` internally to emit a non-terminating error. +1. The engine checks the effective `ErrorAction` preference for the command. +1. Because the preference is `Stop`, the engine creates an + `ActionPreferenceStopException` that wraps the original error record. +1. If caught by `catch`, the original error information is accessible through + `$_.Exception.ErrorRecord`. + +The scope of the escalated error depends on context: + +- In **non-advanced** scripts, functions, or script blocks, setting + `$ErrorActionPreference = 'Stop'` escalates to a **script-terminating** + error. The error propagates up the call stack. +- In **advanced** functions and script blocks (those with `[CmdletBinding()]`), + the error remains **statement-terminating**. Execution continues at the next + statement after the call. +- Passing `-ErrorAction Stop` to an advanced function has the same effect as + setting `$ErrorActionPreference = 'Stop'` inside it, because `-ErrorAction` + translates to a scope-local `$ErrorActionPreference` value. + +### Escalation examples + +- NON-advanced: script-terminating ('after' does NOT print) + + ```powershell + & { + param() + $ErrorActionPreference = 'Stop' + Get-Item 'NoSuchPath' + } 2>$null + 'after' + ``` + +- ADVANCED: statement-terminating ('after' DOES print) + + ```powershell + & { + [CmdletBinding()] + param() + $ErrorActionPreference = 'Stop'; Get-Item 'NoSuchPath' + } 2>$null + 'after' + ``` + +- Without `-ErrorAction Stop`: non-terminating, catch doesn't run + + ```powershell + try { + Write-Error 'This is non-terminating' + Write-Output 'Execution continues' + } catch { + Write-Output "Caught: $_" # Not reached + } + ``` + +- With `-ErrorAction Stop`: escalated to terminating + + ```powershell + try { + Write-Error 'This becomes terminating' -ErrorAction Stop + } catch { + Write-Output "Caught: $_" # Reached + } + ``` + +Escalated errors can be caught by their original exception type. The engine +unwraps the `ActionPreferenceStopException` to find the underlying exception: + +```powershell +try { + Get-Item -Path 'C:\NoSuchFile.txt' -ErrorAction Stop +} catch [System.Management.Automation.ItemNotFoundException] { + Write-Output "File not found: $($_.Exception.Message)" +} +``` + +### The `$ErrorActionPreference` asymmetry + +The `-ErrorAction` parameter and the `$ErrorActionPreference` variable behave +differently with terminating errors. It's important to understand this +asymmetry: + +- `-ErrorAction` only affects **non-terminating** errors. When a cmdlet calls + `$PSCmdlet.ThrowTerminatingError()`, the `-ErrorAction` parameter is ignored + (except for `Break`, which enters the debugger). The error is always thrown. + +- `$ErrorActionPreference` affects **both** non-terminating and + statement-terminating errors. The engine's statement-level error handler + reads `$ErrorActionPreference` (not the `-ErrorAction` parameter) and can + suppress a statement-terminating error when the value is `SilentlyContinue` + or `Ignore`. + +```powershell +function Test-Asymmetry { + [CmdletBinding()] + param() + $er = [System.Management.Automation.ErrorRecord]::new( + [System.InvalidOperationException]::new('test error'), + 'TestError', + [System.Management.Automation.ErrorCategory]::InvalidOperation, + $null + ) + $PSCmdlet.ThrowTerminatingError($er) +} + +# -ErrorAction SilentlyContinue does NOT suppress the error: +Test-Asymmetry -ErrorAction SilentlyContinue # Error is still thrown + +# $ErrorActionPreference DOES suppress the error: +$ErrorActionPreference = 'SilentlyContinue' +Test-Asymmetry # Error is silently suppressed, script continues +$ErrorActionPreference = 'Continue' +``` + +> [!IMPORTANT] +> `$ErrorActionPreference` can't suppress errors that have +> `SuppressPromptInInterpreter` set to `true`. These always propagate +> regardless of the preference variable. Examples of this type of error +> include: +> +> - `ActionPreferenceStopException` from `-ErrorAction Stop` escalation +> - Errors inside PowerShell class methods +> - `PipelineStoppedException` + +## Handle errors + +### `try/catch/finally` + +Use `try/catch/finally` to handle statement-terminating and script-terminating +errors. When an error occurs inside a `try` block, PowerShell searches for a +matching `catch` block. The `finally` block always runs, whether or not an +error occurred. + +```powershell +try { + $result = Get-Content -Path 'data.txt' -ErrorAction Stop +} +catch [System.Management.Automation.ItemNotFoundException] { + Write-Warning 'Data file not found, using defaults.' + $result = 'default' +} +catch { + Write-Warning "Unexpected error: $_" +} +finally { + Write-Verbose 'Cleanup complete.' -Verbose +} +``` + +Inside a `try` block, the engine sets an internal flag that causes non- +terminating errors escalated by `-ErrorAction Stop` or +`$ErrorActionPreference = 'Stop'` to propagate to the `catch` block. This +is designed behavior, not a special case. + +For full syntax details, see [about_Try_Catch_Finally][12]. + +### `trap` + +The `trap` statement handles terminating errors at the scope level. When an +error occurs anywhere in the enclosing scope, the `trap` block runs. + +- **Default** (no `break` or `continue`): The error is displayed and execution + continues at the next statement after the one that caused the error. +- **`continue`** in the trap: Suppresses the error message and resumes at the + next statement. +- **`break`** in the trap: The error propagates to the parent scope. + +```powershell +trap [System.Management.Automation.CommandNotFoundException] { + Write-Warning "Command not found: $($_.TargetObject)" + continue +} + +NonsenseCommand # Trap fires, execution continues +Write-Output 'This runs because the trap used continue' +``` + +For full syntax details, see [about_Trap][11]. + +## Reporting errors in functions and scripts + +When writing functions and scripts, choose the error-reporting mechanism that +matches the severity of the failure. + +### Non-terminating - use `Write-Error` + +Use `Write-Error` when the function can continue processing other input. This +is appropriate for pipeline functions that process multiple objects and +encounter failures on individual items. + +```powershell +function Test-Path-Safe { + [CmdletBinding()] + param([Parameter(ValueFromPipeline)][string]$Path) + process { + if (-not (Test-Path $Path)) { + Write-Error "Path not found: $Path" + return + } + $Path + } +} +``` + +> [!NOTE] +> In advanced functions (those with `[CmdletBinding()]`), use +> `$PSCmdlet.WriteError()` instead of `Write-Error` to ensure that `$?` is +> properly set to `$false` in the caller's scope. The `Write-Error` cmdlet +> doesn't always set `$?` correctly. + +### Statement-terminating - use `$PSCmdlet.ThrowTerminatingError()` + +Use `$PSCmdlet.ThrowTerminatingError()` when the function can't continue at all +but the caller should decide how to handle the failure. This is the recommended +approach in advanced functions. + +```powershell +function Get-Config { + [CmdletBinding()] + param([string]$Path) + + if (-not (Test-Path $Path)) { + $er = [System.Management.Automation.ErrorRecord]::new( + [System.IO.FileNotFoundException]::new("Config file not found: $Path"), + 'ConfigNotFound', + [System.Management.Automation.ErrorCategory]::ObjectNotFound, + $Path + ) + $PSCmdlet.ThrowTerminatingError($er) + } + + Get-Content $Path | ConvertFrom-Json +} +``` + +After the error leaves the function, the caller treats it as a non-terminating +error by default. The caller can escalate it with `-ErrorAction Stop`. + +### Script-terminating - use `throw` + +Use `throw` when recovery isn't possible and the entire script should stop. + +```powershell +$config = Get-Content 'config.json' -ErrorAction SilentlyContinue | + ConvertFrom-Json + +if (-not $config) { + throw 'Cannot proceed without a valid configuration file.' +} +``` + +### Which mechanism to use + +- When processing multiple inputs where some may fail, use `Write-Error` or + `$PSCmdlet.WriteError()`. +- If the function can't continue, use `$PSCmdlet.ThrowTerminatingError()` and + let the caller decide how to handle it. +- If the entire script must stop immediately, use `throw`. + +## Summary of error types + +The following tables summarize the properties and behaviors of the different +error types in PowerShell. + +### Non-terminating error + +[Non-terminating errors][02] can be generated by `Write-Error` or +`$PSCmdlet.WriteError()`. + +| Attribute | Description | +| ------------------------------------ | ------------------------------- | +| Scope of impact | Pipeline continues | +| Caught by `catch` | No (unless escalated) | +| Caught by `trap` | No (unless escalated) | +| Added to `$Error` | Yes (unless `Ignore`) | +| Sets `$?` to `$false` | Yes | +| Affected by `-ErrorAction` | Yes | +| Affected by `$ErrorActionPreference` | Yes | + +### Statement-terminating error + +[Statement-terminating errors][04] can be generated by +`ThrowTerminatingError()`, engine errors, .NET method exceptions, or +`-ErrorAction Stop` in advanced contexts. + +| Attribute | Description | +| ------------------------------------ | ----------------------------------------- | +| Scope of impact | Current statement stops; script continues | +| Caught by `catch` | Yes | +| Caught by `trap` | Yes | +| Added to `$Error` | Yes | +| Sets `$?` to `$false` | Yes | +| Affected by `-ErrorAction` | No (`Break` only) | +| Affected by `$ErrorActionPreference` | Yes (can suppress) | + +### Script-terminating error + +[Script-terminating errors][03] can be generated by `throw`, parse errors, or +`-ErrorAction Stop` in non-advanced contexts. + +| Attribute | Description | +| ------------------------------------ | ----------------------------- | +| Scope of impact | Call stack unwinds | +| Caught by `catch` | Yes | +| Caught by `trap` | Yes | +| Added to `$Error` | Yes | +| Sets `$?` to `$false` | Yes | +| Affected by `-ErrorAction` | No | +| Affected by `$ErrorActionPreference` | `throw`: Yes (can suppress) | +| Affected by `$ErrorActionPreference` | Escalated: depends on context | + +## See also + +- [about_Automatic_Variables][06] +- [about_CommonParameters][07] +- [about_Preference_Variables][09] +- [about_Output_Streams][08] +- [about_Throw][10] +- [about_Trap][11] +- [about_Try_Catch_Finally][12] + + +[01]: #how-escalation-works +[02]: #non-terminating-errors +[03]: #script-terminating-errors +[04]: #statement-terminating-errors +[05]: #the-erroractionpreference-asymmetry +[06]: about_Automatic_Variables.md +[07]: about_CommonParameters.md +[08]: about_Output_Streams.md +[09]: about_Preference_Variables.md +[10]: about_Throw.md +[11]: about_Trap.md +[12]: about_Try_Catch_Finally.md diff --git a/reference/7.5/Microsoft.PowerShell.Core/About/about_Preference_Variables.md b/reference/7.5/Microsoft.PowerShell.Core/About/about_Preference_Variables.md index 1e7626c2b1a..66480d8a2a1 100644 --- a/reference/7.5/Microsoft.PowerShell.Core/About/about_Preference_Variables.md +++ b/reference/7.5/Microsoft.PowerShell.Core/About/about_Preference_Variables.md @@ -1,7 +1,7 @@ --- description: Variables that customize the behavior of PowerShell. Locale: en-US -ms.date: 12/01/2025 +ms.date: 04/02/2026 online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_preference_variables?view=powershell-7.5&WT.mc_id=ps-gethelp schema: 2.0.0 title: about_Preference_Variables @@ -388,25 +388,32 @@ The valid values are as follows: raised. - **Continue**: (Default) Displays the error message and continues executing. - **Ignore**: Suppresses the error message and continues to execute the - command. The **Ignore** value is intended for per-command use, not for use as - saved preference. **Ignore** isn't a valid value for the - `$ErrorActionPreference` variable. + command. Unlike **SilentlyContinue**, **Ignore** doesn't add the error + message to the `$Error` automatic variable. The **Ignore** value is also + valid for `$ErrorActionPreference`, where it suppresses both non-terminating + and statement-terminating errors. However, **Ignore** only prevents `$Error` + recording for non-terminating errors. Terminating errors that are suppressed + by `Ignore` are still recorded in `$Error`. - **Inquire**: Displays the error message and asks you whether you want to continue. - **SilentlyContinue**: No effect. The error message isn't displayed and execution continues without interruption. - **Stop**: Displays the error message and stops executing. In addition to the - error generated, the **Stop** value generates an ActionPreferenceStopException - object to the error stream. + error generated, the **Stop** value generates an + ActionPreferenceStopException object to the error stream. - **Suspend**: Automatically suspends a workflow job to allow for further investigation. After investigation, the workflow can be resumed. The **Suspend** value is intended for per-command use, not for use as saved preference. **Suspend** isn't a valid value for the `$ErrorActionPreference` variable. -`$ErrorActionPreference` and the **ErrorAction** parameter don't affect how -PowerShell responds to terminating errors that stop cmdlet processing. For more -information about the **ErrorAction** common parameter, see +`$ErrorActionPreference` applies to **both** non-terminating and +statement-terminating errors. Unlike the `-ErrorAction` parameter (which only +affects non-terminating errors), the preference variable can also suppress or +escalate errors generated by `$PSCmdlet.ThrowTerminatingError()`. When set to +**Stop**, it escalates non-terminating errors to script-terminating errors. For +more information about error categories, see [about_Error_Handling][67]. For +more information about the **ErrorAction** common parameter, see [about_CommonParameters][29]. Many native commands write to `stderr` as an alternative stream for additional @@ -419,10 +426,9 @@ like when using redirection operators (`2>&1`), aren't written to the `$Error` variable and the preference variable `$ErrorActionPreference` doesn't affect the redirected output. -PowerShell 7.3 added an experimental feature that allows you to control how -messages written to `stderr` are handled. - -For more information see, [$PSNativeCommandUseErrorActionPreference][18]. +PowerShell 7.4 added a feature that allows you to control how messages written +to `stderr` are handled. For more information, see +[$PSNativeCommandUseErrorActionPreference][18]. ### Examples @@ -1692,6 +1698,7 @@ At line:1 char:1 - [about_Automatic_Variables][28] - [about_CommonParameters][29] - [about_Environment_Variables][30] +- [about_Error_Handling][67] - [about_Profiles][36] - [about_Remote][39] - [about_Scopes][40] @@ -1763,3 +1770,4 @@ At line:1 char:1 [64]: xref:System.Text.UTF7Encoding [65]: xref:System.Text.UTF8Encoding [66]: about_Functions_CmdletBindingAttribute.md +[67]: about_Error_Handling.md diff --git a/reference/7.5/Microsoft.PowerShell.Core/About/about_Throw.md b/reference/7.5/Microsoft.PowerShell.Core/About/about_Throw.md index de3604500a8..b4c853e26cd 100644 --- a/reference/7.5/Microsoft.PowerShell.Core/About/about_Throw.md +++ b/reference/7.5/Microsoft.PowerShell.Core/About/about_Throw.md @@ -1,7 +1,7 @@ --- -description: Describes the `throw` keyword, which generates a terminating error. +description: Describes the `throw` keyword, which generates a script-terminating error by default. Locale: en-US -ms.date: 01/18/2026 +ms.date: 04/02/2026 online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_throw?view=powershell-7.5&WT.mc_id=ps-gethelp schema: 2.0.0 title: about_Throw @@ -10,12 +10,30 @@ title: about_Throw ## Short description -Describes the `throw` keyword that generates a terminating error. +Describes the `throw` keyword, which generates a script-terminating error by +default. ## Long description -The `throw` keyword causes a terminating error. You can use the `throw` keyword -to stop the processing of a command, function, or script. +The `throw` keyword causes a script-terminating error by default. You can use +the `throw` keyword to stop the processing of a command, function, or script. + +Unlike statement-terminating errors, the `throw` keyword unwinds the entire +call stack. Execution stops completely unless the error is caught by a +`try/catch` block or `trap` statement. + +> [!NOTE] +> `$ErrorActionPreference` can suppress `throw`. When set to `SilentlyContinue` +> or `Ignore`, the error doesn't propagate and execution continues at the next +> statement. When calling an advanced function with +> `-ErrorAction SilentlyContinue`, the parameter translates to a scope-local +> `$ErrorActionPreference` value, so it also suppresses `throw` inside that +> function. Even when suppressed, `throw` still records an entry in `$Error`. +> The `Ignore` value only prevents `$Error` recording for non-terminating +> errors like those generated by `$PSCmdlet.ThrowTerminatingError()`. + +For more information about error categories and `$ErrorActionPreference` +behavior, see [about_Error_Handling][03]. For example, you can use the `throw` keyword in the statement block of an `if` statement to respond to a condition or in the `catch` block of a @@ -46,7 +64,7 @@ Exception: ScriptHalted If the `throw` keyword is used in a `catch` block without an expression, it throws the current RuntimeException again. For more information, see -[about_Try_Catch_Finally](about_Try_Catch_Finally.md). +[about_Try_Catch_Finally][07]. ## Throwing a string @@ -116,13 +134,23 @@ object is automatically saved in the `$Error` automatic variable. Unlike past versions of PowerShell, don't use the `throw` keyword for parameter validation. See -[about_Functions_Advanced_Parameters](about_Functions_Advanced_Parameters.md) +[about_Functions_Advanced_Parameters][04] for the correct way. ## See also -- [about_Break](about_Break.md) -- [about_Continue](about_Continue.md) -- [about_Scopes](about_Scopes.md) -- [about_Trap](about_Trap.md) -- [about_Try_Catch_Finally](about_Try_Catch_Finally.md) +- [about_Break][01] +- [about_Continue][02] +- [about_Error_Handling][03] +- [about_Scopes][05] +- [about_Trap][06] +- [about_Try_Catch_Finally][07] + + +[01]: about_Break.md +[02]: about_Continue.md +[03]: about_Error_Handling.md +[04]: about_Functions_Advanced_Parameters.md +[05]: about_Scopes.md +[06]: about_Trap.md +[07]: about_Try_Catch_Finally.md diff --git a/reference/7.5/Microsoft.PowerShell.Core/About/about_Trap.md b/reference/7.5/Microsoft.PowerShell.Core/About/about_Trap.md index 37514e43fdc..dea91ef86e2 100644 --- a/reference/7.5/Microsoft.PowerShell.Core/About/about_Trap.md +++ b/reference/7.5/Microsoft.PowerShell.Core/About/about_Trap.md @@ -1,7 +1,7 @@ --- -description: Describes a keyword that handles a terminating error. +description: Describes a keyword that handles statement-terminating and script-terminating errors. Locale: en-US -ms.date: 01/13/2026 +ms.date: 04/02/2026 online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_trap?view=powershell-7.5&WT.mc_id=ps-gethelp schema: 2.0.0 title: about_Trap @@ -10,14 +10,16 @@ title: about_Trap ## Short description -Describes a keyword that handles a terminating error. +Describes a keyword that handles statement-terminating and script-terminating +errors. ## Long description -A terminating error stops a statement from running. If PowerShell doesn't -handle a terminating error in some way, PowerShell also stops running the -function or script in the current pipeline. In other languages, such as C#, -terminating errors are known as exceptions. +A terminating error stops a statement from running. PowerShell distinguishes +_statement-terminating_ errors (which stop only the current statement) from +_script-terminating_ errors (which unwind the entire call stack). The `trap` +keyword can handle both kinds. For more information about error categories, see +[about_Error_Handling][07]. The `trap` keyword specifies a list of statements to run when a terminating error occurs. `trap` statements can handle the terminating errors in the @@ -286,7 +288,7 @@ after loop In the output, you can see the loops continue until the last iteration. When the script tries to divide 1 by 0, PowerShell throws a terminating error. The -script skips the rest of the `foreach` statement, runs the `try` statement, +script skips the rest of the `foreach` statement, runs the `trap` statement, and continues after the `foreach` statement. ## Trapping errors and scope @@ -468,6 +470,7 @@ statement. For more information, see - [about_Break][01] - [about_Continue][02] +- [about_Error_Handling][07] - [about_Scopes][03] - [about_Throw][04] - [about_Try_Catch_Finally][05] @@ -479,3 +482,4 @@ statement. For more information, see [04]: about_Throw.md [05]: about_Try_Catch_Finally.md [06]: https://wikipedia.org/wiki/JavaScript_syntax#hoisting +[07]: about_Error_Handling.md diff --git a/reference/7.5/Microsoft.PowerShell.Core/About/about_Try_Catch_Finally.md b/reference/7.5/Microsoft.PowerShell.Core/About/about_Try_Catch_Finally.md index 676b01d7179..f422b8fab6b 100644 --- a/reference/7.5/Microsoft.PowerShell.Core/About/about_Try_Catch_Finally.md +++ b/reference/7.5/Microsoft.PowerShell.Core/About/about_Try_Catch_Finally.md @@ -1,7 +1,7 @@ --- -description: Describes how to use the `try`, `catch`, and `finally` blocks to handle terminating errors. +description: Describes how to use the `try`, `catch`, and `finally` blocks to handle statement-terminating and script-terminating errors. Locale: en-US -ms.date: 01/13/2026 +ms.date: 04/02/2026 online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_try_catch_finally?view=powershell-7.5&WT.mc_id=ps-gethelp schema: 2.0.0 title: about_Try_Catch_Finally @@ -11,18 +11,31 @@ title: about_Try_Catch_Finally ## Short description Describes how to use the `try`, `catch`, and `finally` blocks to handle -terminating errors. +statement-terminating and script-terminating errors. ## Long description Use `try`, `catch`, and `finally` blocks to respond to or handle terminating -errors in scripts. The `trap` statement can also be used to handle terminating -errors in scripts. For more information, see [about_Trap][05]. +errors in scripts. PowerShell has two kinds of terminating errors: -A terminating error stops a statement from running. If PowerShell does not -handle a terminating error in some way, PowerShell also stops running the -function or script using the current pipeline. In other languages, such as C\#, -terminating errors are referred to as exceptions. +- _statement-terminating_ errors that stop the current statement and +- _script-terminating_ errors that unwind the entire call stack + +Both kinds are caught by `try/catch`. You can also use the `trap` statement to +handle terminating errors. For more information, see [about_Trap][05]. For a +comprehensive overview of all error types, see [about_Error_Handling][06]. + +A statement-terminating error stops the current statement from running, but +PowerShell continues at the next statement unless the error is also +script-terminating. A script-terminating error (such as an error produced by +the `throw` keyword) stops the entire script unless caught by a `try/catch` +block or `trap` statement. + +> [!NOTE] +> `$ErrorActionPreference` can suppress `throw`. When set to `SilentlyContinue` +> or `Ignore`, the error doesn't propagate and execution continues at the next +> statement. For details, see the _Script-terminating errors_ section of +> [about_Error_Handling][07]. Use the `try` block to define a section of a script in which you want PowerShell to monitor for errors. When an error occurs within the `try` block, @@ -255,7 +268,7 @@ try { "An error occurred that could not be resolved." } finally { $wc.Dispose() - if (Test-Path $tempPath) { Remove-Item $tempFile } + if (Test-Path $tempFile) { Remove-Item $tempFile } } ``` @@ -263,6 +276,7 @@ try { - [about_Break][01] - [about_Continue][02] +- [about_Error_Handling][06] - [about_Scopes][03] - [about_Throw][04] - [about_Trap][05] @@ -273,3 +287,5 @@ try { [03]: about_Scopes.md [04]: about_Throw.md [05]: about_Trap.md +[06]: about_Error_Handling.md +[07]: about_Error_Handling.md#script-terminating-errors diff --git a/reference/7.6/Microsoft.PowerShell.Core/About/About.md b/reference/7.6/Microsoft.PowerShell.Core/About/About.md index dc02c67bc98..bd30220861a 100644 --- a/reference/7.6/Microsoft.PowerShell.Core/About/About.md +++ b/reference/7.6/Microsoft.PowerShell.Core/About/About.md @@ -167,6 +167,13 @@ Provides access to the Windows environment variables. Describes how to access and manage environment variables in PowerShell. +### [about_Error_Handling](about_Error_Handling.md) + +Describes the three categories of PowerShell errors — non-terminating, +statement-terminating, and script-terminating — and explains how error +action preferences, `try/catch/trap`, and error state variables control +error handling behavior. + ### [about_Execution_Policies](about_Execution_Policies.md) Describes the PowerShell execution policies and explains how to manage them. @@ -589,16 +596,18 @@ the current session process. ### [about_Throw](about_Throw.md) -Describes the `throw` keyword that generates a terminating error. +Describes the `throw` keyword that generates a script-terminating error by +default. ### [about_Trap](about_Trap.md) -Describes a keyword that handles a terminating error. +Describes a keyword that handles statement-terminating and script-terminating +errors. ### [about_Try_Catch_Finally](about_Try_Catch_Finally.md) Describes how to use the `try`, `catch`, and `finally` blocks to handle -terminating errors. +statement-terminating and script-terminating errors. ### [about_Type_Accelerators](about_Type_Accelerators.md) diff --git a/reference/7.6/Microsoft.PowerShell.Core/About/about_Automatic_Variables.md b/reference/7.6/Microsoft.PowerShell.Core/About/about_Automatic_Variables.md index 6abf3a21a87..14ac19a1112 100644 --- a/reference/7.6/Microsoft.PowerShell.Core/About/about_Automatic_Variables.md +++ b/reference/7.6/Microsoft.PowerShell.Core/About/about_Automatic_Variables.md @@ -1,7 +1,7 @@ --- description: Describes variables that store state information for PowerShell. These variables are created and maintained by PowerShell. Locale: en-US -ms.date: 02/10/2026 +ms.date: 04/02/2026 no-loc: [Reset, Current, Background, Blink, Bold, Foreground, Formatting, Hidden, Italic, Reset, Reverse, Underline, PSEventArgs, PSEventSubscriber, PSEdition] online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_automatic_variables?view=powershell-7.6&WT.mc_id=ps-gethelp schema: 2.0.0 @@ -167,8 +167,8 @@ Contains a list of names of the experimental features that are enabled. Contains an array of error objects that represent the most recent errors. The most recent error is the first error object in the array `$Error[0]`. -To prevent an error from being added to the `$Error` array, use the -**ErrorAction** common parameter with a value of **Ignore**. For more +To prevent a non-terminating error from being added to the `$Error` array, use +the **ErrorAction** common parameter with a value of **Ignore**. For more information, see [about_CommonParameters][53]. ### `$Event` diff --git a/reference/7.6/Microsoft.PowerShell.Core/About/about_CommonParameters.md b/reference/7.6/Microsoft.PowerShell.Core/About/about_CommonParameters.md index 4439bc733c1..03100aa3d29 100644 --- a/reference/7.6/Microsoft.PowerShell.Core/About/about_CommonParameters.md +++ b/reference/7.6/Microsoft.PowerShell.Core/About/about_CommonParameters.md @@ -1,7 +1,7 @@ --- description: Describes the parameters that can be used with any cmdlet. Locale: en-US -ms.date: 01/18/2026 +ms.date: 04/02/2026 no-loc: [Confirm, Debug, ErrorAction, ErrorVariable, InformationAction, InformationVariable, OutBuffer, OutVariable, PipelineVariable, ProgressAction, Verbose, WarningAction, WarningVariable, WhatIf] online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_commonparameters?view=powershell-7.6&WT.mc_id=ps-gethelp schema: 2.0.0 @@ -105,8 +105,8 @@ the display of debugging messages when `$DebugPreference` isn't ### -ErrorAction Determines how the cmdlet responds to a non-terminating error from the command. -This parameter works only when the command generates a non-terminating error, -such as those from the `Write-Error` cmdlet. +This parameter overrides the value of the `$ErrorActionPreference` variable for +non-terminating errors generated by the command or the `Write-Error` cmdlet. ```yaml Type: ActionPreference @@ -124,22 +124,28 @@ variable for the current command. Because the default value of the `$ErrorActionPreference` variable is `Continue`, error messages are displayed and execution continues unless you use the `ErrorAction` parameter. -The `ErrorAction` parameter has no effect on terminating errors (such as -missing data, parameters that aren't valid, or insufficient permissions) that -prevent a command from completing successfully. +The `-ErrorAction` parameter doesn't prevent statement-terminating errors +(such as missing data, parameters that aren't valid, or insufficient +permissions) from stopping the current statement. However, when set to `Stop`, +it escalates non-terminating errors to script-terminating errors, making them +catchable by `try/catch`. For more information about error categories, see +[about_Error_Handling][15]. - `Break` Enters the debugger when an error occurs or an exception is raised. - `Continue` displays the error message and continues executing the command. `Continue` is the default. - `Ignore` suppresses the error message and continues executing the command. - Unlike `SilentlyContinue`, `Ignore` doesn't add the error message to the - `$Error` automatic variable. The `Ignore` value is introduced in PowerShell - 3.0. + Unlike `SilentlyContinue`, `Ignore` doesn't add the non-terminating error to + the `$Error` automatic variable. The `Ignore` value is introduced in + PowerShell 3.0. - `Inquire` displays the error message and prompts you for confirmation before continuing execution. This value is rarely used. - `SilentlyContinue` suppresses the error message and continues executing the command. -- `Stop` displays the error message and stops executing the command. +- `Stop` displays the error message and stops executing the command. The + `Stop` value escalates the non-terminating error to a terminating error + by generating an `ActionPreferenceStopException`. The error can then + be caught by a `try/catch` block or `trap` statement. - `Suspend` is only available for workflows which aren't supported in PowerShell 6 and beyond. @@ -817,6 +823,7 @@ Mode LastWriteTime Length Name - [about_Preference_Variables][03] +- [about_Error_Handling][15] - [`Write-Debug`][11] - [`Write-Error`][12] - [`Write-Verbose`][13] @@ -832,4 +839,5 @@ Mode LastWriteTime Length Name [12]: xref:Microsoft.PowerShell.Utility.Write-Error [13]: xref:Microsoft.PowerShell.Utility.Write-Verbose [14]: xref:Microsoft.PowerShell.Utility.Write-Warning +[15]: about_Error_Handling.md diff --git a/reference/7.6/Microsoft.PowerShell.Core/About/about_Error_Handling.md b/reference/7.6/Microsoft.PowerShell.Core/About/about_Error_Handling.md new file mode 100644 index 00000000000..c605c021412 --- /dev/null +++ b/reference/7.6/Microsoft.PowerShell.Core/About/about_Error_Handling.md @@ -0,0 +1,562 @@ +--- +description: Describes the types of errors in PowerShell and the mechanisms for handling them. +Locale: en-US +ms.date: 03/26/2026 +online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_error_handling?view=powershell-7.6&WT.mc_id=ps-gethelp +schema: 2.0.0 +title: about_Error_Handling +--- +# about_Error_Handling + +## Short description + +Describes the types of errors in PowerShell and the mechanisms for handling +them. + +## Long description + +PowerShell distinguishes three categories of errors: + +- Non-terminating errors +- Statement-terminating errors +- Script-terminating errors + +Understanding the distinction is essential for writing reliable scripts and +modules, because each category has different default behavior and requires +different handling techniques. + +Additionally, external (native) programs report failure through exit codes, +which PowerShell tracks separately from its own error system. + +## Types of errors + +### Non-terminating errors + +A non-terminating error reports a problem but doesn't stop the pipeline. The +command continues processing subsequent input objects. Non-terminating errors +are generated by: + +- The `Write-Error` cmdlet +- The `$PSCmdlet.WriteError()` method in advanced functions +- Cmdlets that encounter recoverable failures on individual input objects + +By default, PowerShell displays the error message and continues execution. + +```powershell +# Non-terminating error: the pipeline continues after the failure +'file1.txt', 'noSuchFile.txt', 'file3.txt' | ForEach-Object { + Get-Content $_ -ErrorAction Continue +} +``` + +In this example, `Get-Content` reports a non-terminating error for +`noSuchFile.txt` and then continues processing `file3.txt`. + +Non-terminating errors do **not** trigger `catch` or `trap` by default. + +### Statement-terminating errors + +A statement-terminating error stops the current statement (pipeline) from +running, but execution continues at the next statement in the script. +Statement-terminating errors are generated by: + +- The `$PSCmdlet.ThrowTerminatingError()` method in advanced functions and + compiled cmdlets +- Engine errors such as `CommandNotFoundException` (calling a command that + doesn't exist) and `ParameterBindingException` (invalid parameter arguments) +- .NET method calls that throw exceptions, such as `[int]::Parse('abc')` + +```powershell +# Statement-terminating error: Get-Item fails, but the next statement runs +Get-Item -Path 'C:\NoSuchFile.txt' +Write-Output 'This still runs' +``` + +Statement-terminating errors can be caught by `try/catch` and `trap`. + +> [!NOTE] +> `.ThrowTerminatingError()` doesn't consult the `-ErrorAction` parameter +> (except for the `Break` value, which enters the debugger). However, +> `$ErrorActionPreference` _does_ apply to statement-terminating errors +> through the engine's statement-level handler. For example, +> `$ErrorActionPreference = 'SilentlyContinue'` can suppress a +> statement-terminating error so that the script continues at the next +> statement. The `-ErrorAction` parameter can't do this. For details, see +> [The $ErrorActionPreference asymmetry][05]. + +### Script-terminating errors + +A script-terminating error unwinds the entire call stack. Execution stops +completely unless the error is caught by a `try/catch` block or `trap` +statement. Script-terminating errors are generated by: + +- The `throw` keyword +- Parse errors (syntax errors that prevent the script from being compiled) +- Non-terminating errors **escalated** by `-ErrorAction Stop` or + `$ErrorActionPreference = 'Stop'` in non-advanced contexts. For more + information, see [How escalation works][01]. +- Certain critical engine failures + +```powershell +# Script-terminating error: throw unwinds the call stack +function Test-Throw { + throw 'Critical failure' + Write-Output 'This never runs' +} + +Test-Throw +Write-Output 'This never runs either (unless caught)' +``` + +The `throw` keyword generates a script-terminating error by default. However, +`$ErrorActionPreference` _can_ suppress `throw` when set to `SilentlyContinue` +or `Ignore`. When calling an advanced function with +`-ErrorAction SilentlyContinue`, the parameter translates to a scope-local +`$ErrorActionPreference` value, so it also suppresses `throw` inside that +function. + +> [!NOTE] +> Even with `$ErrorActionPreference = 'Ignore'`, a `throw` that's suppressed +> still records an entry in `$Error`. The `Ignore` value only prevents `$Error` +> recording for **non-terminating** errors. + +> [!IMPORTANT] +> The terms _statement-terminating_ and _script-terminating_ describe the scope +> of impact, not the severity of the error. A statement-terminating error stops +> one statement. A script-terminating error stops the entire script and its +> callers. Both can be caught by `try/catch`. + +### External program errors + +External (native) programs don't participate in PowerShell's error system +directly. They report failure through a non-zero exit code, which PowerShell +stores in the `$LASTEXITCODE` automatic variable. + +```powershell +git clone https://example.com/nonexistent.git 2>$null +if ($LASTEXITCODE -ne 0) { + Write-Error "git failed with exit code $LASTEXITCODE" +} +``` + +By default, a non-zero exit code from a native program: + +- Sets `$?` to `$false` +- Does **not** generate an `ErrorRecord` in `$Error` +- Does **not** trigger `catch` or `trap` + +PowerShell 7.3 added the experimental preference variable +`$PSNativeCommandUseErrorActionPreference`, which became a stable feature in +7.4. When you set this variable to `$true`, it causes a non-zero exit code to +emit a **non-terminating error** whose message states the specific exit code (a +`NativeCommandExitException`). This error respects `$ErrorActionPreference`, so +setting it to `Stop` promotes the error to a script-terminating error that can +be caught with `try`/`catch`. + +## Error state variables + +PowerShell maintains several automatic variables that reflect the current error +state. + +### `$?` + +Contains `$true` if the last operation succeeded and `$false` if it produced +any error (non-terminating or terminating). For native commands, `$?` is set +based on the exit code: `$true` for exit code `0`, `$false` otherwise. + +```powershell +Get-Item -Path 'C:\NoSuchFile.txt' 2>$null +$? # False +``` + +### `$Error` + +An `ArrayList` that stores the most recent error records, with the most recent +error at index `0`. The list holds up to `$MaximumErrorCount` entries (default +256). + +All terminating errors are added to `$Error`. For terminating errors, `Ignore` +suppresses display but still records the error in `$Error`. All non-terminating +are added to `$Error` unless `-ErrorAction Ignore` is used on non-terminating +errors, which prevents both display and recording. + +### `$LASTEXITCODE` + +Contains the exit code of the last native program that ran. A value of `0` +conventionally indicates success. Any non-zero value indicates failure. This +variable isn't affected by PowerShell cmdlet errors. + +## Control error behavior + +### The `-ErrorAction` common parameter + +The `-ErrorAction` common parameter overrides `$ErrorActionPreference` for a +single command. It controls how PowerShell responds to **non-terminating** +errors from that command. + +| Value | Behavior | +| ------------------ | -------------------------------------------------------------------- | +| `Continue` | Display the error and continue (default) | +| `SilentlyContinue` | Suppress display, add to `$Error`, continue | +| `Ignore` | Suppress display and don't add to `$Error` | +| `Stop` | **Escalate** to a terminating error (see [How escalation works][01]) | +| `Inquire` | Prompt the user for a decision | +| `Break` | Enter the debugger | + +`-ErrorAction` doesn't change the behavior of errors generated by +`$PSCmdlet.ThrowTerminatingError()`. Those errors are always +statement-terminating regardless of the caller's preference. + +### The `$ErrorActionPreference `variable + +The `$ErrorActionPreference` preference variable applies to all commands in the +current scope and child scopes. It accepts the same values as `-ErrorAction`. + +```powershell +$ErrorActionPreference = 'Stop' +# All non-terminating errors in this scope now become terminating +Write-Error 'This now throws' # Generates ActionPreferenceStopException +``` + +When `-ErrorAction` is specified on a command, it takes precedence over +`$ErrorActionPreference` for that command. + +### How escalation works + +When `-ErrorAction Stop` or `$ErrorActionPreference = 'Stop'` is in effect, +PowerShell converts non-terminating errors into terminating errors using the +following mechanism: + +1. A cmdlet calls `WriteError()` internally to emit a non-terminating error. +1. The engine checks the effective `ErrorAction` preference for the command. +1. Because the preference is `Stop`, the engine creates an + `ActionPreferenceStopException` that wraps the original error record. +1. If caught by `catch`, the original error information is accessible through + `$_.Exception.ErrorRecord`. + +The scope of the escalated error depends on context: + +- In **non-advanced** scripts, functions, or script blocks, setting + `$ErrorActionPreference = 'Stop'` escalates to a **script-terminating** + error. The error propagates up the call stack. +- In **advanced** functions and script blocks (those with `[CmdletBinding()]`), + the error remains **statement-terminating**. Execution continues at the next + statement after the call. +- Passing `-ErrorAction Stop` to an advanced function has the same effect as + setting `$ErrorActionPreference = 'Stop'` inside it, because `-ErrorAction` + translates to a scope-local `$ErrorActionPreference` value. + +### Escalation examples + +- NON-advanced: script-terminating ('after' does NOT print) + + ```powershell + & { + param() + $ErrorActionPreference = 'Stop' + Get-Item 'NoSuchPath' + } 2>$null + 'after' + ``` + +- ADVANCED: statement-terminating ('after' DOES print) + + ```powershell + & { + [CmdletBinding()] + param() + $ErrorActionPreference = 'Stop'; Get-Item 'NoSuchPath' + } 2>$null + 'after' + ``` + +- Without `-ErrorAction Stop`: non-terminating, catch doesn't run + + ```powershell + try { + Write-Error 'This is non-terminating' + Write-Output 'Execution continues' + } catch { + Write-Output "Caught: $_" # Not reached + } + ``` + +- With `-ErrorAction Stop`: escalated to terminating + + ```powershell + try { + Write-Error 'This becomes terminating' -ErrorAction Stop + } catch { + Write-Output "Caught: $_" # Reached + } + ``` + +Escalated errors can be caught by their original exception type. The engine +unwraps the `ActionPreferenceStopException` to find the underlying exception: + +```powershell +try { + Get-Item -Path 'C:\NoSuchFile.txt' -ErrorAction Stop +} catch [System.Management.Automation.ItemNotFoundException] { + Write-Output "File not found: $($_.Exception.Message)" +} +``` + +### The `$ErrorActionPreference` asymmetry + +The `-ErrorAction` parameter and the `$ErrorActionPreference` variable behave +differently with terminating errors. It's important to understand this +asymmetry: + +- `-ErrorAction` only affects **non-terminating** errors. When a cmdlet calls + `$PSCmdlet.ThrowTerminatingError()`, the `-ErrorAction` parameter is ignored + (except for `Break`, which enters the debugger). The error is always thrown. + +- `$ErrorActionPreference` affects **both** non-terminating and + statement-terminating errors. The engine's statement-level error handler + reads `$ErrorActionPreference` (not the `-ErrorAction` parameter) and can + suppress a statement-terminating error when the value is `SilentlyContinue` + or `Ignore`. + +```powershell +function Test-Asymmetry { + [CmdletBinding()] + param() + $er = [System.Management.Automation.ErrorRecord]::new( + [System.InvalidOperationException]::new('test error'), + 'TestError', + [System.Management.Automation.ErrorCategory]::InvalidOperation, + $null + ) + $PSCmdlet.ThrowTerminatingError($er) +} + +# -ErrorAction SilentlyContinue does NOT suppress the error: +Test-Asymmetry -ErrorAction SilentlyContinue # Error is still thrown + +# $ErrorActionPreference DOES suppress the error: +$ErrorActionPreference = 'SilentlyContinue' +Test-Asymmetry # Error is silently suppressed, script continues +$ErrorActionPreference = 'Continue' +``` + +> [!IMPORTANT] +> `$ErrorActionPreference` can't suppress errors that have +> `SuppressPromptInInterpreter` set to `true`. These always propagate +> regardless of the preference variable. Examples of this type of error +> include: +> +> - `ActionPreferenceStopException` from `-ErrorAction Stop` escalation +> - Errors inside PowerShell class methods +> - `PipelineStoppedException` + +## Handle errors + +### `try/catch/finally` + +Use `try/catch/finally` to handle statement-terminating and script-terminating +errors. When an error occurs inside a `try` block, PowerShell searches for a +matching `catch` block. The `finally` block always runs, whether or not an +error occurred. + +```powershell +try { + $result = Get-Content -Path 'data.txt' -ErrorAction Stop +} +catch [System.Management.Automation.ItemNotFoundException] { + Write-Warning 'Data file not found, using defaults.' + $result = 'default' +} +catch { + Write-Warning "Unexpected error: $_" +} +finally { + Write-Verbose 'Cleanup complete.' -Verbose +} +``` + +Inside a `try` block, the engine sets an internal flag that causes non- +terminating errors escalated by `-ErrorAction Stop` or +`$ErrorActionPreference = 'Stop'` to propagate to the `catch` block. This +is designed behavior, not a special case. + +For full syntax details, see [about_Try_Catch_Finally][12]. + +### `trap` + +The `trap` statement handles terminating errors at the scope level. When an +error occurs anywhere in the enclosing scope, the `trap` block runs. + +- **Default** (no `break` or `continue`): The error is displayed and execution + continues at the next statement after the one that caused the error. +- **`continue`** in the trap: Suppresses the error message and resumes at the + next statement. +- **`break`** in the trap: The error propagates to the parent scope. + +```powershell +trap [System.Management.Automation.CommandNotFoundException] { + Write-Warning "Command not found: $($_.TargetObject)" + continue +} + +NonsenseCommand # Trap fires, execution continues +Write-Output 'This runs because the trap used continue' +``` + +For full syntax details, see [about_Trap][11]. + +## Reporting errors in functions and scripts + +When writing functions and scripts, choose the error-reporting mechanism that +matches the severity of the failure. + +### Non-terminating - use `Write-Error` + +Use `Write-Error` when the function can continue processing other input. This +is appropriate for pipeline functions that process multiple objects and +encounter failures on individual items. + +```powershell +function Test-Path-Safe { + [CmdletBinding()] + param([Parameter(ValueFromPipeline)][string]$Path) + process { + if (-not (Test-Path $Path)) { + Write-Error "Path not found: $Path" + return + } + $Path + } +} +``` + +> [!NOTE] +> In advanced functions (those with `[CmdletBinding()]`), use +> `$PSCmdlet.WriteError()` instead of `Write-Error` to ensure that `$?` is +> properly set to `$false` in the caller's scope. The `Write-Error` cmdlet +> doesn't always set `$?` correctly. + +### Statement-terminating - use `$PSCmdlet.ThrowTerminatingError()` + +Use `$PSCmdlet.ThrowTerminatingError()` when the function can't continue at all +but the caller should decide how to handle the failure. This is the recommended +approach in advanced functions. + +```powershell +function Get-Config { + [CmdletBinding()] + param([string]$Path) + + if (-not (Test-Path $Path)) { + $er = [System.Management.Automation.ErrorRecord]::new( + [System.IO.FileNotFoundException]::new("Config file not found: $Path"), + 'ConfigNotFound', + [System.Management.Automation.ErrorCategory]::ObjectNotFound, + $Path + ) + $PSCmdlet.ThrowTerminatingError($er) + } + + Get-Content $Path | ConvertFrom-Json +} +``` + +After the error leaves the function, the caller treats it as a non-terminating +error by default. The caller can escalate it with `-ErrorAction Stop`. + +### Script-terminating - use `throw` + +Use `throw` when recovery isn't possible and the entire script should stop. + +```powershell +$config = Get-Content 'config.json' -ErrorAction SilentlyContinue | + ConvertFrom-Json + +if (-not $config) { + throw 'Cannot proceed without a valid configuration file.' +} +``` + +### Which mechanism to use + +- When processing multiple inputs where some may fail, use `Write-Error` or + `$PSCmdlet.WriteError()`. +- If the function can't continue, use `$PSCmdlet.ThrowTerminatingError()` and + let the caller decide how to handle it. +- If the entire script must stop immediately, use `throw`. + +## Summary of error types + +The following tables summarize the properties and behaviors of the different +error types in PowerShell. + +### Non-terminating error + +[Non-terminating errors][02] can be generated by `Write-Error` or +`$PSCmdlet.WriteError()`. + +| Attribute | Description | +| ------------------------------------ | ------------------------------- | +| Scope of impact | Pipeline continues | +| Caught by `catch` | No (unless escalated) | +| Caught by `trap` | No (unless escalated) | +| Added to `$Error` | Yes (unless `Ignore`) | +| Sets `$?` to `$false` | Yes | +| Affected by `-ErrorAction` | Yes | +| Affected by `$ErrorActionPreference` | Yes | + +### Statement-terminating error + +[Statement-terminating errors][04] can be generated by +`ThrowTerminatingError()`, engine errors, .NET method exceptions, or +`-ErrorAction Stop` in advanced contexts. + +| Attribute | Description | +| ------------------------------------ | ----------------------------------------- | +| Scope of impact | Current statement stops; script continues | +| Caught by `catch` | Yes | +| Caught by `trap` | Yes | +| Added to `$Error` | Yes | +| Sets `$?` to `$false` | Yes | +| Affected by `-ErrorAction` | No (`Break` only) | +| Affected by `$ErrorActionPreference` | Yes (can suppress) | + +### Script-terminating error + +[Script-terminating errors][03] can be generated by `throw`, parse errors, or +`-ErrorAction Stop` in non-advanced contexts. + +| Attribute | Description | +| ------------------------------------ | ----------------------------- | +| Scope of impact | Call stack unwinds | +| Caught by `catch` | Yes | +| Caught by `trap` | Yes | +| Added to `$Error` | Yes | +| Sets `$?` to `$false` | Yes | +| Affected by `-ErrorAction` | No | +| Affected by `$ErrorActionPreference` | `throw`: Yes (can suppress) | +| Affected by `$ErrorActionPreference` | Escalated: depends on context | + +## See also + +- [about_Automatic_Variables][06] +- [about_CommonParameters][07] +- [about_Preference_Variables][09] +- [about_Output_Streams][08] +- [about_Throw][10] +- [about_Trap][11] +- [about_Try_Catch_Finally][12] + + +[01]: #how-escalation-works +[02]: #non-terminating-errors +[03]: #script-terminating-errors +[04]: #statement-terminating-errors +[05]: #the-erroractionpreference-asymmetry +[06]: about_Automatic_Variables.md +[07]: about_CommonParameters.md +[08]: about_Output_Streams.md +[09]: about_Preference_Variables.md +[10]: about_Throw.md +[11]: about_Trap.md +[12]: about_Try_Catch_Finally.md diff --git a/reference/7.6/Microsoft.PowerShell.Core/About/about_Preference_Variables.md b/reference/7.6/Microsoft.PowerShell.Core/About/about_Preference_Variables.md index d8f018167d3..940162af2f9 100644 --- a/reference/7.6/Microsoft.PowerShell.Core/About/about_Preference_Variables.md +++ b/reference/7.6/Microsoft.PowerShell.Core/About/about_Preference_Variables.md @@ -1,7 +1,7 @@ --- description: Variables that customize the behavior of PowerShell. Locale: en-US -ms.date: 12/01/2025 +ms.date: 04/02/2026 online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_preference_variables?view=powershell-7.6&WT.mc_id=ps-gethelp schema: 2.0.0 title: about_Preference_Variables @@ -388,25 +388,32 @@ The valid values are as follows: raised. - **Continue**: (Default) Displays the error message and continues executing. - **Ignore**: Suppresses the error message and continues to execute the - command. The **Ignore** value is intended for per-command use, not for use as - saved preference. **Ignore** isn't a valid value for the - `$ErrorActionPreference` variable. + command. Unlike **SilentlyContinue**, **Ignore** doesn't add the error + message to the `$Error` automatic variable. The **Ignore** value is also + valid for `$ErrorActionPreference`, where it suppresses both non-terminating + and statement-terminating errors. However, **Ignore** only prevents `$Error` + recording for non-terminating errors. Terminating errors that are suppressed + by `Ignore` are still recorded in `$Error`. - **Inquire**: Displays the error message and asks you whether you want to continue. - **SilentlyContinue**: No effect. The error message isn't displayed and execution continues without interruption. - **Stop**: Displays the error message and stops executing. In addition to the - error generated, the **Stop** value generates an ActionPreferenceStopException - object to the error stream. + error generated, the **Stop** value generates an + ActionPreferenceStopException object to the error stream. - **Suspend**: Automatically suspends a workflow job to allow for further investigation. After investigation, the workflow can be resumed. The **Suspend** value is intended for per-command use, not for use as saved preference. **Suspend** isn't a valid value for the `$ErrorActionPreference` variable. -`$ErrorActionPreference` and the **ErrorAction** parameter don't affect how -PowerShell responds to terminating errors that stop cmdlet processing. For more -information about the **ErrorAction** common parameter, see +`$ErrorActionPreference` applies to **both** non-terminating and +statement-terminating errors. Unlike the `-ErrorAction` parameter (which only +affects non-terminating errors), the preference variable can also suppress or +escalate errors generated by `$PSCmdlet.ThrowTerminatingError()`. When set to +**Stop**, it escalates non-terminating errors to script-terminating errors. For +more information about error categories, see [about_Error_Handling][67]. For +more information about the **ErrorAction** common parameter, see [about_CommonParameters][29]. Many native commands write to `stderr` as an alternative stream for additional @@ -419,10 +426,9 @@ like when using redirection operators (`2>&1`), aren't written to the `$Error` variable and the preference variable `$ErrorActionPreference` doesn't affect the redirected output. -PowerShell 7.3 added an experimental feature that allows you to control how -messages written to `stderr` are handled. - -For more information see, [$PSNativeCommandUseErrorActionPreference][18]. +PowerShell 7.4 added a feature that allows you to control how messages written +to `stderr` are handled. For more information, see +[$PSNativeCommandUseErrorActionPreference][18]. ### Examples @@ -1692,6 +1698,7 @@ At line:1 char:1 - [about_Automatic_Variables][28] - [about_CommonParameters][29] - [about_Environment_Variables][30] +- [about_Error_Handling][67] - [about_Profiles][36] - [about_Remote][39] - [about_Scopes][40] @@ -1763,3 +1770,4 @@ At line:1 char:1 [64]: xref:System.Text.UTF7Encoding [65]: xref:System.Text.UTF8Encoding [66]: about_Functions_CmdletBindingAttribute.md +[67]: about_Error_Handling.md diff --git a/reference/7.6/Microsoft.PowerShell.Core/About/about_Throw.md b/reference/7.6/Microsoft.PowerShell.Core/About/about_Throw.md index b905c6af7f2..e1db3291922 100644 --- a/reference/7.6/Microsoft.PowerShell.Core/About/about_Throw.md +++ b/reference/7.6/Microsoft.PowerShell.Core/About/about_Throw.md @@ -1,7 +1,7 @@ --- -description: Describes the `throw` keyword, which generates a terminating error. +description: Describes the `throw` keyword, which generates a script-terminating error by default. Locale: en-US -ms.date: 01/18/2026 +ms.date: 04/02/2026 online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_throw?view=powershell-7.6&WT.mc_id=ps-gethelp schema: 2.0.0 title: about_Throw @@ -10,12 +10,30 @@ title: about_Throw ## Short description -Describes the `throw` keyword that generates a terminating error. +Describes the `throw` keyword, which generates a script-terminating error by +default. ## Long description -The `throw` keyword causes a terminating error. You can use the `throw` keyword -to stop the processing of a command, function, or script. +The `throw` keyword causes a script-terminating error by default. You can use +the `throw` keyword to stop the processing of a command, function, or script. + +Unlike statement-terminating errors, the `throw` keyword unwinds the entire +call stack. Execution stops completely unless the error is caught by a +`try/catch` block or `trap` statement. + +> [!NOTE] +> `$ErrorActionPreference` can suppress `throw`. When set to `SilentlyContinue` +> or `Ignore`, the error doesn't propagate and execution continues at the next +> statement. When calling an advanced function with +> `-ErrorAction SilentlyContinue`, the parameter translates to a scope-local +> `$ErrorActionPreference` value, so it also suppresses `throw` inside that +> function. Even when suppressed, `throw` still records an entry in `$Error`. +> The `Ignore` value only prevents `$Error` recording for non-terminating +> errors like those generated by `$PSCmdlet.ThrowTerminatingError()`. + +For more information about error categories and `$ErrorActionPreference` +behavior, see [about_Error_Handling][03]. For example, you can use the `throw` keyword in the statement block of an `if` statement to respond to a condition or in the `catch` block of a @@ -46,7 +64,7 @@ Exception: ScriptHalted If the `throw` keyword is used in a `catch` block without an expression, it throws the current RuntimeException again. For more information, see -[about_Try_Catch_Finally](about_Try_Catch_Finally.md). +[about_Try_Catch_Finally][07]. ## Throwing a string @@ -116,13 +134,23 @@ object is automatically saved in the `$Error` automatic variable. Unlike past versions of PowerShell, don't use the `throw` keyword for parameter validation. See -[about_Functions_Advanced_Parameters](about_Functions_Advanced_Parameters.md) +[about_Functions_Advanced_Parameters][04] for the correct way. ## See also -- [about_Break](about_Break.md) -- [about_Continue](about_Continue.md) -- [about_Scopes](about_Scopes.md) -- [about_Trap](about_Trap.md) -- [about_Try_Catch_Finally](about_Try_Catch_Finally.md) +- [about_Break][01] +- [about_Continue][02] +- [about_Error_Handling][03] +- [about_Scopes][05] +- [about_Trap][06] +- [about_Try_Catch_Finally][07] + + +[01]: about_Break.md +[02]: about_Continue.md +[03]: about_Error_Handling.md +[04]: about_Functions_Advanced_Parameters.md +[05]: about_Scopes.md +[06]: about_Trap.md +[07]: about_Try_Catch_Finally.md diff --git a/reference/7.6/Microsoft.PowerShell.Core/About/about_Trap.md b/reference/7.6/Microsoft.PowerShell.Core/About/about_Trap.md index 1a59f55c709..d740940722d 100644 --- a/reference/7.6/Microsoft.PowerShell.Core/About/about_Trap.md +++ b/reference/7.6/Microsoft.PowerShell.Core/About/about_Trap.md @@ -1,7 +1,7 @@ --- -description: Describes a keyword that handles a terminating error. +description: Describes a keyword that handles statement-terminating and script-terminating errors. Locale: en-US -ms.date: 01/13/2026 +ms.date: 04/02/2026 online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_trap?view=powershell-7.6&WT.mc_id=ps-gethelp schema: 2.0.0 title: about_Trap @@ -10,14 +10,16 @@ title: about_Trap ## Short description -Describes a keyword that handles a terminating error. +Describes a keyword that handles statement-terminating and script-terminating +errors. ## Long description -A terminating error stops a statement from running. If PowerShell doesn't -handle a terminating error in some way, PowerShell also stops running the -function or script in the current pipeline. In other languages, such as C#, -terminating errors are known as exceptions. +A terminating error stops a statement from running. PowerShell distinguishes +_statement-terminating_ errors (which stop only the current statement) from +_script-terminating_ errors (which unwind the entire call stack). The `trap` +keyword can handle both kinds. For more information about error categories, see +[about_Error_Handling][07]. The `trap` keyword specifies a list of statements to run when a terminating error occurs. `trap` statements can handle the terminating errors in the @@ -286,7 +288,7 @@ after loop In the output, you can see the loops continue until the last iteration. When the script tries to divide 1 by 0, PowerShell throws a terminating error. The -script skips the rest of the `foreach` statement, runs the `try` statement, +script skips the rest of the `foreach` statement, runs the `trap` statement, and continues after the `foreach` statement. ## Trapping errors and scope @@ -468,6 +470,7 @@ statement. For more information, see - [about_Break][01] - [about_Continue][02] +- [about_Error_Handling][07] - [about_Scopes][03] - [about_Throw][04] - [about_Try_Catch_Finally][05] @@ -479,3 +482,4 @@ statement. For more information, see [04]: about_Throw.md [05]: about_Try_Catch_Finally.md [06]: https://wikipedia.org/wiki/JavaScript_syntax#hoisting +[07]: about_Error_Handling.md diff --git a/reference/7.6/Microsoft.PowerShell.Core/About/about_Try_Catch_Finally.md b/reference/7.6/Microsoft.PowerShell.Core/About/about_Try_Catch_Finally.md index 82b449f6813..53c343547c5 100644 --- a/reference/7.6/Microsoft.PowerShell.Core/About/about_Try_Catch_Finally.md +++ b/reference/7.6/Microsoft.PowerShell.Core/About/about_Try_Catch_Finally.md @@ -1,7 +1,7 @@ --- -description: Describes how to use the `try`, `catch`, and `finally` blocks to handle terminating errors. +description: Describes how to use the `try`, `catch`, and `finally` blocks to handle statement-terminating and script-terminating errors. Locale: en-US -ms.date: 01/13/2026 +ms.date: 04/02/2026 online version: https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_try_catch_finally?view=powershell-7.6&WT.mc_id=ps-gethelp schema: 2.0.0 title: about_Try_Catch_Finally @@ -11,18 +11,31 @@ title: about_Try_Catch_Finally ## Short description Describes how to use the `try`, `catch`, and `finally` blocks to handle -terminating errors. +statement-terminating and script-terminating errors. ## Long description Use `try`, `catch`, and `finally` blocks to respond to or handle terminating -errors in scripts. The `trap` statement can also be used to handle terminating -errors in scripts. For more information, see [about_Trap][05]. +errors in scripts. PowerShell has two kinds of terminating errors: -A terminating error stops a statement from running. If PowerShell does not -handle a terminating error in some way, PowerShell also stops running the -function or script using the current pipeline. In other languages, such as C\#, -terminating errors are referred to as exceptions. +- _statement-terminating_ errors that stop the current statement and +- _script-terminating_ errors that unwind the entire call stack + +Both kinds are caught by `try/catch`. You can also use the `trap` statement to +handle terminating errors. For more information, see [about_Trap][05]. For a +comprehensive overview of all error types, see [about_Error_Handling][06]. + +A statement-terminating error stops the current statement from running, but +PowerShell continues at the next statement unless the error is also +script-terminating. A script-terminating error (such as an error produced by +the `throw` keyword) stops the entire script unless caught by a `try/catch` +block or `trap` statement. + +> [!NOTE] +> `$ErrorActionPreference` can suppress `throw`. When set to `SilentlyContinue` +> or `Ignore`, the error doesn't propagate and execution continues at the next +> statement. For details, see the _Script-terminating errors_ section of +> [about_Error_Handling][07]. Use the `try` block to define a section of a script in which you want PowerShell to monitor for errors. When an error occurs within the `try` block, @@ -255,7 +268,7 @@ try { "An error occurred that could not be resolved." } finally { $wc.Dispose() - if (Test-Path $tempPath) { Remove-Item $tempFile } + if (Test-Path $tempFile) { Remove-Item $tempFile } } ``` @@ -263,6 +276,7 @@ try { - [about_Break][01] - [about_Continue][02] +- [about_Error_Handling][06] - [about_Scopes][03] - [about_Throw][04] - [about_Trap][05] @@ -273,3 +287,5 @@ try { [03]: about_Scopes.md [04]: about_Throw.md [05]: about_Trap.md +[06]: about_Error_Handling.md +[07]: about_Error_Handling.md#script-terminating-errors diff --git a/reference/docs-conceptual/learn/deep-dives/everything-about-exceptions.md b/reference/docs-conceptual/learn/deep-dives/everything-about-exceptions.md index 17b065c9f7d..363d9f3e786 100644 --- a/reference/docs-conceptual/learn/deep-dives/everything-about-exceptions.md +++ b/reference/docs-conceptual/learn/deep-dives/everything-about-exceptions.md @@ -1,7 +1,7 @@ --- description: Error handling is just part of life when it comes to writing code. ms.custom: contributor-KevinMarquette -ms.date: 06/20/2024 +ms.date: 04/02/2026 title: Everything you wanted to know about exceptions --- # Everything you wanted to know about exceptions @@ -12,9 +12,9 @@ can easily handle exceptions generated by other people's code or you can generat exceptions for others to handle. > [!NOTE] -> The [original version][07] of this article appeared on the blog written by [@KevinMarquette][08]. +> The [original version][08] of this article appeared on the blog written by [@KevinMarquette][09]. > The PowerShell team thanks Kevin for sharing this content with us. Please check out his blog at -> [PowerShellExplained.com][05]. +> [PowerShellExplained.com][06]. ## Basic terminology @@ -44,12 +44,18 @@ it. ### Terminating and non-terminating errors -An exception is generally a terminating error. A thrown exception is either be caught or it -terminates the current execution. By default, a non-terminating error is generated by `Write-Error` -and it adds an error to the output stream without throwing an exception. +PowerShell has three categories of errors. -I point this out because `Write-Error` and other non-terminating errors do not trigger the -`catch`. +- A _non-terminating error_ adds an error to the error stream without stopping execution and doesn't + trigger `catch`. By default, `Write-Error` generates non-terminating errors. +- A _statement-terminating error_ stops the current statement but allows the script to continue at + the next statement. Statement-terminating errors can be generated by engine errors, + `$PSCmdlet.ThrowTerminatingError()`, or .NET method exceptions. +- A _script-terminating error_ unwinds the entire call stack. Script-terminating errors can be + generated by `throw`, parse errors, or `-ErrorAction Stop` escalation. + +Both statement-terminating and script-terminating errors can be caught by `try/catch`. For a +comprehensive reference, see [about_Error_Handling][04]. ### Swallowing an exception @@ -71,7 +77,7 @@ function Start-Something } ``` -This creates a runtime exception that is a terminating error. It's handled by a `catch` in a +This creates a runtime exception that is a script-terminating error. It's handled by a `catch` in a calling function or exits the script with a message like this. ```powershell @@ -107,7 +113,7 @@ Start-Something -ErrorAction Stop ``` For more information about the **ErrorAction** parameter, see [about_CommonParameters][03]. For more -information about the `$ErrorActionPreference` variable, see [about_Preference_Variables][04]. +information about the `$ErrorActionPreference` variable, see [about_Preference_Variables][05]. ### Try/Catch @@ -426,7 +432,7 @@ catch [System.IO.FileNotFoundException] I compiled a master list with the help of the Reddit `r/PowerShell` community that contains hundreds of .NET exceptions to complement this post. -- [The big list of .NET exceptions][06] +- [The big list of .NET exceptions][07] I start by searching that list for exceptions that feel like they would be a good fit for my situation. You should try to use exceptions in the base `System` namespace. @@ -556,53 +562,52 @@ catch This changes the source of the error to the Cmdlet and hide the internals of your function from the users of your Cmdlet. -## Try can create terminating errors +## How try/catch changes error propagation -Kirk Munro points out that some exceptions are only terminating errors when executed inside a -`try/catch` block. Here is the example he gave me that generates a divide by zero runtime exception. +Inside a `try` block, PowerShell sets an internal flag that causes all statement-terminating errors +to propagate to the `catch` block. This is by design, not a corner case. The following example +demonstrates this behavior. ```powershell function Start-Something { 1/(1-1) } ``` -Then invoke it like this to see it generate the error and still output the message. +Outside `try/catch`, a statement-terminating error from a child scope doesn't stop the parent scope. +Here is a function that generates a divide by zero runtime exception. + +Invoke it like this to see the error reported while the script continues. ```powershell &{ Start-Something; Write-Output "We did it. Send Email" } ``` -But by placing that same code inside a `try/catch`, we see something else happen. +But placing that same code inside a `try/catch`, the error propagates to the `catch` block. ```powershell -try -{ +try { &{ Start-Something; Write-Output "We did it. Send Email" } -} -catch -{ +} catch { Write-Output "Notify Admin to fix error and send email" } ``` -We see the error become a terminating error and not output the first message. What I don't like -about this one is that you can have this code in a function and it acts differently if someone is -using a `try/catch`. - -I have not ran into issues with this myself but it is corner case to be aware of. +The error is caught and the subsequent `Write-Output` inside the script block doesn't run. This is +standard `try/catch` behavior — all terminating errors within the `try` block are caught, whether +they originate in the current scope or in a child scope. ### $PSCmdlet.ThrowTerminatingError() inside try/catch -One nuance of `$PSCmdlet.ThrowTerminatingError()` is that it creates a terminating error within your -Cmdlet but it turns into a non-terminating error after it leaves your Cmdlet. This leaves the burden -on the caller of your function to decide how to handle the error. They can turn it back into a -terminating error by using `-ErrorAction Stop` or calling it from within a `try{...}catch{...}`. +`$PSCmdlet.ThrowTerminatingError()` creates a statement-terminating error within the cmdlet. After +the error leaves the cmdlet, the caller treats it as a non-terminating error by default. The caller +can escalate it back to a terminating error by using `-ErrorAction Stop` or calling it from within a +`try/catch` block. ### Public function templates -One last takeaway I had with my conversation with Kirk Munro was that he places a -`try{...}catch{...}` around every `begin`, `process` and `end` block in all of his advanced -functions. In those generic catch blocks, he has a single line using -`$PSCmdlet.ThrowTerminatingError($PSItem)` to deal with all exceptions leaving his functions. +One last takeaway I had with my conversation with Kirk Munro was that he places a `try/catch` block +inside every `begin`, `process` and `end` block in all his advanced functions. In those generic +catch blocks, he has a single line using `$PSCmdlet.ThrowTerminatingError($PSItem)` to deal with all +exceptions leaving his functions. ```powershell function Start-Something @@ -612,12 +617,9 @@ function Start-Something process { - try - { + try { ... - } - catch - { + } catch { $PSCmdlet.ThrowTerminatingError($PSItem) } } @@ -667,8 +669,9 @@ advice and make `ThrowTerminatingError` my goto exception handler for every func [01]: /dotnet/api [02]: /dotnet/api/System.IO.FileNotFoundException [03]: /powershell/module/microsoft.powershell.core/about/about_commonparameters -[04]: /powershell/module/microsoft.powershell.core/about/about_preference_variables -[05]: https://powershellexplained.com/ -[06]: https://powershellexplained.com/2017-04-07-all-dotnet-exception-list -[07]: https://powershellexplained.com/2017-04-10-Powershell-exceptions-everything-you-ever-wanted-to-know/ -[08]: https://twitter.com/KevinMarquette +[04]: /powershell/module/microsoft.powershell.core/about/about_error_handling +[05]: /powershell/module/microsoft.powershell.core/about/about_preference_variables +[06]: https://powershellexplained.com/ +[07]: https://powershellexplained.com/2017-04-07-all-dotnet-exception-list +[08]: https://powershellexplained.com/2017-04-10-Powershell-exceptions-everything-you-ever-wanted-to-know/ +[09]: https://twitter.com/KevinMarquette