PowerShell DISCUSSION

PowerShell try/catch does not catch the error from a cmdlet: how do terminating errors work?

Started by vannhan PowerShell try catchErrorAction Stopterminating errorsLASTEXITCODEErrorActionPreference
4 replies 248 views 5 participants
Latest activity · 30 Sep 2026

PowerShell try/catch does not catch the error from a cmdlet: how do terminating errors work?

vannhan PowerShell Forum
#1

My deployment script wraps a copy step in try { Copy-Item $src $dest -Recurse } catch { Write-Host "copy failed"; exit 1 }. When the source path is wrong, the red error text appears but the catch block never runs and the script continues with the next step. The same happens when an external tool such as robocopy or git fails.

Why is the error not caught, and how do I make the script stop on the first failure?

Community replies 4

Re: PowerShell try/catch does not catch the error from a cmdlet: how do terminating errors work?

#2

PowerShell has two kinds of error. A terminating error stops the current statement and can be caught; examples are throw, exceptions from .NET method calls and invalid parameters. A non-terminating error is what most cmdlets produce for a problem with one item: the cmdlet writes an error record, then carries on with the next item. That design lets Get-ChildItem skip one unreadable folder instead of aborting, but try/catch only sees terminating errors.

Promote the error for that command with -ErrorAction Stop: Copy-Item $src $dest -Recurse -ErrorAction Stop now lands in the catch block.

Re: PowerShell try/catch does not catch the error from a cmdlet: how do terminating errors work?

#3

To apply that to the whole script, set $ErrorActionPreference = 'Stop' at the top. Every cmdlet error then becomes terminating unless a command overrides it with its own -ErrorAction.

Inside catch, the variable $_ is the error record: $_.Exception.Message is the text, $_.InvocationInfo.ScriptLineNumber the line. You can catch specific types first and everything else after, for example catch [System.Management.Automation.ItemNotFoundException] { ... } catch { ... }, and a finally { ... } block runs whether or not an error occurred, which is the place for cleanup.

Re: PowerShell try/catch does not catch the error from a cmdlet: how do terminating errors work?

#4

External programs are a separate case. An executable does not raise PowerShell errors; it returns an exit code, available in $LASTEXITCODE straight after the call. Check it yourself: git pull; if ($LASTEXITCODE -ne 0) { throw "git failed with exit code $LASTEXITCODE" }.

Know the tool's convention before testing for zero. robocopy uses its exit code as a set of flags, and values below 8 mean the run completed without failures (1 means files were copied), so the right test there is -ge 8. In PowerShell 7.4 and later, setting $PSNativeCommandUseErrorActionPreference = $true makes a non-zero exit code follow the error preference automatically.

Re: PowerShell try/catch does not catch the error from a cmdlet: how do terminating errors work?

#5

A few habits that keep error handling honest. Do not silence problems with an empty catch { } or a blanket -ErrorAction SilentlyContinue; if an error is expected, handle that one case and log it. -ErrorVariable copyErrors collects a command's non-terminating errors so that you can count them afterwards without stopping midway.

In your own functions, use throw for failures the caller must not ignore; Write-Error is non-terminating by default. Finally, end a failed script with a non-zero code such as exit 1 so that a scheduler or build server calling it sees the failure.

TEP COMMUNITY