-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Our Error Handling, Ourselves - time to fully understand and properly document PowerShell's error handling #1583
Comments
@juanpablojofre this would make a great about topic |
A note about In the following script, [CmdletBinding()]
param()
$caught = 'not-caught'
try {
# this is not caught in v5 (works in v2)
$PSCmdlet.ThrowTerminatingError((New-Object System.Management.Automation.ErrorRecord ([Exception]'some-error'), $null, 0, $null))
}
catch {
$caught = 'was-caught'
throw
}
finally {
$caught
'in-finally'
} |
@mklement0 I see your recommendation to utilize Im testing this in Powershell 5.1 If erroractionpreference = stop and you use $PSCmdlet.WriteError() it appears to produce a locally non-terminating error but when it leaves the function it appears to be terminating. That error is not catch-able in the function producing the error but is catche-able by the caller. If erroractionpreference = stop and you use write-error it appears to produce a statement terminating error which can be caught by the function.
Running Test-WriteError will terminate the script:
Running Test-Write-Error will not terminate the script:
In other words, $PSCmdlet.WriteError does not appear to throw a terminating error when $ErrorActionPreference = Stop whereas write-error does |
@strawgate: Thanks for pointing out that difference - I have no explanation for it. To me, your discovery suggests that one currently should always use While you could argue that technically You don't want to catch your own attempts with There is no good solution to this problem with
|
@mklement0 Thank you very much for your excellent post. It has been invaluable to me for making sense of a number of things. Script Terminating Errors vs ExceptionsIs there a difference between "script-terminating errors" and exceptions? There seems to be places in the PowerShell project that distinguish between "script-terminating errors" and exceptions. I haven't, however, been able to observe a difference between them. Is there a difference? What's the "Script" in "Script-Terminating Error"?What is "script" meant to refer to in "script-terminating errors"? It seems like "script-terminating errors" often (almost always in my use of PowerShell) do something other than terminate a script. It seems like the only case where the stack unwinding caused by a "script-terminating error" stops at something that would be called a "script" is where there happens to be nothing that catches the "script-terminating error". Am I missing something? Is there some other definition of "script" that applies to "Script-Terminating Error"? .ThrowTerminatingError does not a Statement-Terminating Error MakeThe original post includes the following statements:
Consider, however, that function e {
try { 1 }
catch{ Write-Host 'catch upstream' }
}
function f {
param ( [Parameter(ValueFromPipeline)]$x )
process {
# nonexistentcommand
$PSCmdlet.ThrowTerminatingError(
[System.Management.Automation.ErrorRecord]::new(
'exception message',
'errorId',
[System.Management.Automation.ErrorCategory]::InvalidOperation,
$null
)
)
}
}
try
{
e | f
Write-Host 'statement following statement with .ThrowTerminatingError'
}
catch
{
Write-Host 'outer catch'
} outputs |
@alx9r: Thanks for the nice feedback and digging deeper. I'll need more time to give your post the attention it deserves, but let me say up front that it was I who came up with the term "script-terminating", out of necessity, given that the existing docs made no distinction between the sub-types of terminating errors. Thus, there's nothing authoritative about this term, and if it turns out to be a misnomer, we should change it. |
Disclaimer: Little of what I state below has been arrived at through source-code analysis. All readers are welcome to point out any misinformation.
From what I understand, all PowerShell errors (as opposed to stderr output from external utilities) are exceptions under the hood.
Presumably, the In practice, what I call a script-terminating error, when uncaught:
Again, the most descriptive term is open to debate.
In this context, the pipeline as a whole is the statement, even though a pipeline is itself by definition composed of sub-statements (an expression or command as the 1st segment, and commands as the subsequent segments). Again, the terminology is open to debate: If an actual pipeline is involved, you could argue that pipeline-terminating error is the better choice, but note that that doesn't apply to expression-only statements such as Another example to demonstrate the pipeline behavior of a statement-terminating error: # Advanced function that generates a statement-(pipeline-)terminating error
# when the input object is integer 2
function f {
param ([Parameter(ValueFromPipeline)] [int] $i)
begin { write-host 'before2' }
process {
if ($i -eq 2) {
$PSCmdlet.ThrowTerminatingError(
[System.Management.Automation.ErrorRecord]::new(
'exception message',
'errorId',
[System.Management.Automation.ErrorCategory]::InvalidOperation,
$null
)
)
}
$i
}
end { write-host 'after2' }
}
# Send an 3-element array through the pipeline whose 2nd element triggers the statement-terminating error.
1, 2, 3 | % { write-host 'before1' } { $_ } { write-host 'after1' } | f The above yields:
That is, the entire pipeline was instantly terminated when the statement-terminating error was generated (no further input objects were processed, and the |
Since I came across this post months ago I've been trying to arrive at empirical proof of the various statements in the OP about "terminating", "non-terminating", "script-terminating", and "statement-terminating" errors. Currently I am doubtful that there exists definitions of those terms that would result in a useful taxonomy of PowerShell errors. I have found few useful generalizations about PowerShell errors that stand up to testing. Most hypotheses involving generalizations and nuance (including some in OP) can be disproven with a small amount of testing. The truth about PowerShell errors seems remarkably resistant to simplicity. I am fairly confident, however, that the following generalizations about PowerShell errors are true:
More nuanced generalizations would, of course, be useful. Currently, however, I am skeptical that such generalizations can be found and proven. Indeed my attempts at doing so have seemed sisyphean. From my perspective the useful takeaway from this exercise is currently the following:
|
My writing the OP had multiple intents:
|
@mklement0 I think we are on the same page in striving for a better record of PowerShell error behavior.
As far as I'm concerned your OP succeeds at this. And I am very thankful that you wrote it.
I think your OP is probably as close to "fundamentally" correct as I've seen. The problem is that there are so many exceptions and nuances to the "fundamental" behavior that "knowing" the "fundamentals" is not particularly useful.
The truth of PowerShell errors is sufficiently messy that I am not convinced that there are objective fundamentals that your summary could be "off" from. I think it is probably useful for me to continue to report repros of newly-surprising error handling behavior. I'm not sure what the best venue for that is, but when I encounter behavior that is sufficiently inscrutable, I expect to continue reporting it to the PowerShell/PowerShell repository.
It seems to me that making PowerShell errors less byzantine would involve numerous breaking changes. I don't think that would be a good way forward. It seems like we are mostly stuck with the current PowerShell error behavior. |
@Kriegel if you want to change that, Write-Error is not the best tool for it. Instead, mark the function with function Get-Err {
[CmdletBinding()]
param()
# function code
} And from there, you can use |
@vexx32 |
… to support PS Core Background: PowerShell/PowerShell#4534 MicrosoftDocs/PowerShell-Docs#1583
Strict modes don't seem to have been discussed, but they introduce yet another nuance into the domain. Here's one dichotomy... First, context:
Then this shows that using an undefined variable generates an error but doesn't stop execution:
But the same script block run with Invoke() generates an exception, not just an error:
It would have been much nicer of course if strict mode always produced an exception, regardless of ErrorActionPreference. |
@johndog, good idea to cover strict-mode violations too; I've just updated the initial post. The short of it is that strict-mode violations result in statement-terminating errors by default. This applies to both your examples, which only differ in the scope of what constitutes the statement being terminated:
Note that while PowerShell's error handling is built on .NET exceptions (in the case of the two flavors of terminating errors), it's better to discuss it in terms of non-terminating vs. statement-terminating vs. script-terminating errors. |
Trying to wrap my head around pipeline execution and statement-terminating behavior. From all the posts and comments, I gathered the understanding that the following two methods can both be used to provoke a statement-terminating behavior.
But in my tests they do not behave the same. The first example continues the pipeline, whereas the second terminates the pipeline. Can someone explain where my understanding is wrong?
On another note, can someone point me to a resource that explains how exactly objects get processed when passed through the pipeline operator (in what order). I do not quite understand the order of operation in this comment: |
Thus, A better comparison of the two scenarios would be: # First statement on each line prints error only; 'after' still prints.
1, (1 / 0), 2 | Write-Output; 'after'
1, (0 | calc), 2 | Write-Output; 'after' Now both errors terminate the entire statement (which happens to be a pipeline in this example, but it equally applies to an expression) and there is no success output. However the next statement ( Perhaps the following addresses your second question: Note that something like By contrast, if you use # First statement on each line prints 1, then error, then 2; 'after' still prints.
& { 1; (1 / 0); 2 } | Write-Output; 'after'
& { 1; (0 | calc); 2 } | Write-Output; 'after'
|
We all know that external utilities returning a non-zero exit code do not terminate a powershell script. However, most do not know (and neither did I) that it is impossible to promote error exit codes to script-terminating errors with ErrorActionPreference. Explicitly check the return codes and Exit. MicrosoftDocs/PowerShell-Docs#1583 Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1368>
@mklement0 |
Origin Location of Errors from Explicitly-Invoked ScriptblocksThe resulting error objects that arise in a PowerShell
Consider files containing scriptblocks according to the following table:
By invoking each of those scriptblocks using one of the calling methods inside a
This suggests the following:
|
The existing help topics that touch on error handling (about_Throw,
about_CommonParameters,
about_Preference_Variables, about_Trap, about_Try_Catch_Finally
):
have sown longstanding confusion due to conflating the two distinct types of terminating errors:
.ThrowTerminatingError()
method) and by expressions in which a .NET exception / a PS runtime error occurs.Throw
or by escalating one of the other error types via error-action preference-variable / parameter valueStop
.have always contained the incorrect claim that the error-action preference / parameter values only pertain to non-terminating errors - which is true for the
-ErrorAction
parameter, but not the$ErrorActionPreference
preference variable - see Clarify the intended behavior/documentation/terminology of terminating errors PowerShell/PowerShell#4292However,
$ErrorActionPreference
withSilentlyContinue
andIgnore
- which in isolation silences all errors, including terminating ones - is preempted by an enclosingtry
/catch
statement or applicabletrap
statement. That is, in the presence of these constructs - only -$ErrorActionPreference
in effect then does not apply to terminating errors, which are then still caught - see Throw outside Try\Trap acts like a non-terminating error PowerShell/PowerShell#19500 (comment)Arguably,
-ErrorAction
too should apply to all error types (as appropriate), though changing hat would certainly be a breaking change - see Cmdlet.ThrowTerminatingError() is not affected by-ErrorAction
PowerShell/PowerShell#14819It's time to:
correct the existing topics
provide a conceptual
about_Error_Handling
topic, as @GoateePFE suggests - see Need an about_Error_Handling topic #1424Below is my understanding of how PowerShell's error handling actually works as of Windows PowerShell v5.1 / PowerShell Core v7.3.4, which can serve as a starting point for
about_Error_Handling
, along with links to issues to related problems.Do tell me if and where I got things wrong.
The sheer complexity of PowerShell's current error handling is problematic, though I do realize that making changes in this area is a serious backward-compatibility concern.
Types of errors:
True PowerShell errors:
Non-terminating errors are issued by cmdlets or functions to signal failure with respect to specific inputs while continuing to process further (pipeline) input by default.
This allows potentially long-running commands to run to completion, despite partial failure. The errors reported can then be inspected via the error records collected in automatic variable
$Error
, allowing reprocessing of only the failed objects later (see below).Note, however, that is possible for all input objects to cause nonterminating errors, amounting to complete failure overall.
Most cmdlet errors are non-terminating errors; e.g.:
'/NoSuch', '/' | Get-Item
reports an error for non-existent path/NoSuch
, but continues processing with valid path/
.Terminating errors:
Invoke-Command
) or implicit (e.g., via modules using implicit remoting) - terminating errors (of either kind) are converted to non-terminating ones.Script-terminating (fatal) errors:
try
/catch
orTrap
statement can prevent hat.Throw
keyword.-ErrorAction
PowerShell/PowerShell#14819 (comment) for a technical discussion.Statement-terminating errors are the (statement-level) counterparts to non-terminating errors: they terminate the enclosing statement (pipeline or expression) and are issued to signal that a statement encountered a problem that doesn't allow it to meaningfully start or continue processing.
-Process
) script block of aForEach-Object
call does NOT terminate the pipeline as a whole - see below for an example.nosuch -l # no such command exists
Get-Item -Foo # -Foo is an invalid parameter name
Select-Object -First notanumber # -First expects an [int]
Set-StrictMode
-Version 1
or higher is in effect).via PowerShell expression runtime errors; e.g.:
1 / 0
via exceptions thrown by .NET method calls; e.g.:
[int]::Parse('foo')
via statement-terminating errors that occurs inside a
(...)
subexpression (but not inside$(...)
or@(...)
, which are independent statement contexts); e.g.:(Get-Item -Foo) + 'hi'
is a statement composed of a single expression that is terminated as a whole; by contrast,$(Get-Item -Foo) + 'hi'
is a statement composed of an expression and an embedded statement, so only the$(...)
part is terminated -+ 'hi'
is still executed.$()
and@()
would therefore have been [array] substatement operators rather than [array] subexpression operators.Failures signaled by external utilities (command-line / console applications such as
findstr.exe
on Windows and terminal-based utilities such asawk
on Unix) via their exit codes are non-terminating - in fact, external utilities reporting nonzero exit codes are not errors in a PowerShell sense.0
) or failed overall (nonzero exit code), with no further distinction.$LASTEXITCODE
variable - see below.Default error actions, logging and success indicators:
Default actions when errors occur:
a non-terminating error:
$ErrorView
can be used to change to a different format.$Error
collection (see below)a statement-terminating error:
-Process
) script block of aForEach-Object
call does NOT terminate the pipeline as a whole - it only terminates the script-block invocation at hand.1, 2 | ForEach-Object -Process { Get-Item -Foo } -End { 'pipeline ran to completion' }
Get-Item -Foo
calls cause statement-terminating errors, but the statements they terminate are the instances of the-Process
script blocks, so pipeline processing continues, andpipeline ran to completion
prints.$Error
collection.a script-terminating error:
$Error
collection (which only matters if the session isn't terminated as a whole)an external utility signaling failure by exit code / producing stderr output:
$Error
collectionDefault success indicators:
Automatic Boolean variable
$?
reflects whether the most recent statement, including calls to external utilities, experienced any error:$True
, if none, and$False
, if at least one error occurred (because, in the case of non-terminating errors, multiple errors may have occurred).In short:
$?
returning$False
tells you only that some error occurred:Caveat: Because
$?
is set by every statement, its value is only meaningful immediately after the statement of interest.$?
is NOT set / set as expected in the following cases:Try/Catch
orTrap
statement - unless theCatch
handler is empty. (Non-terminating errors cannot be caught that way.)Catch
orFinally
block present, the success of whatever statement appears last inside of them, if any, determines what$?
is set to, with a (non-empty)Finally
block taking precedence.(...)
- which turns the command into an expression - it is then the expression's own success that is reflected in$?
:(Get-Item /NoSuch); $?
yields$True
, because the expression itself - whose sole purpose was to wrap the command - technically succeeded.(Get-Item -Foo); $?
yields$False
, because the statement-terminating error terminated the expression as a whole.When calling external utilities, automatic variable
$LASTEXITCODE
complements$?
by containing the specific exit code set by the most recently executed external utility.$?
is set to$True
if the utility's exit code was0
, and to$False
otherwise.Note that while
$?
is only meaningful immediately after the statement of interest,$LASTEXITCODE
remains relevant until the next external-utility call is made; either way, however, it is preferable to save the value in another variable if it needs to be inspected later.Note: Currently, PowerShell lacks operators that allow chaining of commands based on whether they indicate success or not, such as the
&&
and||
control operators in Bash:Default logging:
$Error
variable in reverse chronological order (most recent error first; i.e.,$Error[0]
refers to the most recent error):$Error
is a collection of type[System.Collections.ArrayList]
and the errors are stored as error records of type[System.Management.Automation.ErrorRecord]
that wrap the underlying .NET exception, which all errors ultimately are (instances of[System.Exception]
or a derived type).To inspect
$Error
items, pipe them toFormat-List -Force
(direct output would result in the same format as when the error originally occurred); e.g.:$Error[0] | Format-List -Force
You can clear the collection anytime with
$Error.Clear()
Errors are NOT logged in the following circumstances:
When non-terminating errors occur in a cmdlet / advanced function to which
-ErrorAction Ignore
was passed (see below).What external utilities print to stderr is not considered error output, therefore it is NOT logged in
$Error
(see below).Modifying the default error actions and logging behavior:
PowerShell commands and expressions:
Via common parameter
-ErrorAction
or preference variable$ErrorActionPreference
:Per the documentation as of this writing, specifying an error action should only affect non-terminating errors.
-ErrorAction
common parameter, it is incorrect with respect to the$ErrorActionPreference
preference variable, which affects terminating errors as well (see Clarify the intended behavior/documentation/terminology of terminating errors PowerShell/PowerShell#4292).try
/catch
statement at a higher level can apparently preempt$ErrorActionPreference
- see try/catch overrides $ErrorActionPreference? PowerShell/PowerShell#5693-ErrorAction
common parameter should affect terminating errors too, but changing that would be a major breaking change. - see Cmdlet.ThrowTerminatingError() is not affected by-ErrorAction
PowerShell/PowerShell#14819-ErrorAction
value gets automatically translated into a script/function-local$ErrorActionPreference
value, which with-ErrorAction SilentlyContinue
can result inthrow
statements getting ignored and unwanted code execution - see Throw outside Try\Trap acts like a non-terminating error PowerShell/PowerShell#19500 (comment)In the context of remoting, terminating errors (of either type) are converted to non-terminating ones.
-ErrorAction
nor$ErrorActionPreference
work as expected:-ErrorAction
is applied remotely, which means that whatever errors occur is invariably converted to a non-terminating error locally.$ErrorActionPreference
value (unless it happens to be the global variable value) is not seen by the implicitly remoting module (which is typically an auto-generated script module), because modules have their own namespaces that only inherit from the global scope. The current inability of a script module to opt into the caller's preferences (without cumbersome workarounds) is discussed here: Need straightforward way to honor the caller's preference-variable values / inherited common parameters in functions defined in script modules PowerShell/PowerShell#4568The supported action values are:
Continue
... non-terminating errors only: output errors and log them, but continue processing the current statement (non-terminating errors).Stop
... non-terminating errors and statement-terminating errors via$ErrorActionPreference
only: escalate the error to a script-terminating one.SilentlyContinue
... likeContinue
, but silence error output, while still logging errors. Via$ErrorActionPreference
only, also applies to both types of terminating errors (processing continues).Ignore
(-ErrorAction
parameter only) ... non-terminating errors only: likeSilentlyContinue
, but without logging errors in$Error
. Due toIgnore
not being supported via$ErrorActionPreference
, n/a to terminating errors.$ErrorActionPreference
toIgnore
, even though you shouldn't be able to: Preventing setting 'Ignore' as the $ErrorActionPreference value is poorly enforced on the command line, and not at all in scripts PowerShell/PowerShell#4348-ErrorAction Ignore
to an advanced function currently causes a spurious statement-terminating error - see -ErrorAction Ignore doesn't work for calling advanced functions PowerShell/PowerShell#1759Inquire
... prompt the user for the desired action, including the option to temporarily enter a nested session for debugging. Via$ErrorActionPreference
only, also applies to both types of terminating errors.Suspend
(workflows only) ... automatically suspends a workflow job to allow for investigation.Ad-hoc, when calling cmdlet/advanced functions, you can pass common parameter
-ErrorAction
to modify the behavior of non-terminating errors (only!).-ErrorAction
parameter has no impact on terminating errors - in line with documented, but debatable behavior.Scope-wide (including descendant scopes, unless overridden there), you can set preference variable
$ErrorActionPreference
, which sets the scope's default behavior for all occurrences of non-terminating behaviors, and - against documented behavior - also for terminating errors.Caveat: Advanced functions defined in script modules do not see the caller's preference variables by default, and making them do so is currently quite cumbersome - see Need straightforward way to honor the caller's preference-variable values / inherited common parameters in functions defined in script modules PowerShell/PowerShell#4568
As stated, cmdlets invoked via an implicit-remoting modules also do not see the caller's preference variables.
The
-ErrorAction
parameter takes precedence over the$ErrorActionPreference
variable.Non-terminating errors:
2>$null
, analogous to silencing stderr output from external utilities (see below). Terminating errors ignore2>$null
2>$null
or redirected to file with2>$file
is nonetheless still recorded in the$Error
collection, by design - see Using a 2> error-stream redirection with cmdlets still records error records in $Error PowerShell/PowerShell#4572-ErrorVariable
, unless-ErrorAction Ignore
is also used. Note that use of-ErrorVariable
does not affect the error output behavior; e.g., with error actionContinue
in effect, non-terminating errors still print to the console, whether or not you use-ErrorAction
.Catching terminating errors with
Try
/Catch
orTrap
statements:Important: Only terminating errors (of either type) can be caught this way, and
Try
/Catch
andTrap
are effective irrespective of the current$ErrorActionPreference
value (and any-ErrorAction
common parameter, which fundamentally only applies to non-terminating errors).Inside a
Catch
block:$_
contains the[System.Management.Automation.ErrorRecord]
instance representing the terminating error at hand.Throw
(without an argument) to re-throw the error at hand.You may define multiple
Catch
blocks by applying optional filters based on the underlying .NET exception types - seeGet-Help about_Try_Catch_Finally
.Error logging: Errors caught this way are still logged in the
$Error
collection, but there is debate around that - see Why do handled exceptions show in ErrorVariable? PowerShell/PowerShell#3768External utilities:
Given that an external utility signaling failure by returning a nonzero exit code is not a true PowerShell error:
A failure signaled this way cannot be escalated to a script-terminating error via the
$ErrorActionPreference
variable.Error messages (printed to stderr) are formatted like regular output and are NOT logged in the automatic
$Error
collection variable, nor do they affect how automatic variable$?
is set (that is solely based the utility's exit code).However, you can capture stderr output for later inspection:
Using output redirection
2>
allows you to suppress stderr output or send it to a file:whoami invalidarg 2>$null
suppresses stderr output;whoami invalidarg 2>err.txt
captures stderr output in fileerr.txt
Caveat: Due to a bug still present as of PowerShell Core v6.0.0-beta.5, when you use any
2>
redirection (redirection of PowerShell's error stream):Stderr lines are unexpectedly collected in the
$Error
collection, despite the redirection, and even though stderr output is by default NOT collected in$Error
.This can accidentally trigger a script-terminating error if
$ErrorActionPreference = 'Stop'
happens to be in effect.See Redirecting stderr / the error stream can trigger script-terminating errors PowerShell/PowerShell#4002
There is currently no convenient mechanism for collections stderr lines in a variable, but, as a workaround, you can use redirection
2>&1
to merge stderr output into PowerShell's success output stream (interleaved with stdout output), which allows you to filter out the stderr messages later by type, because PowerShell wraps the stderr lines in[System.Management.Automation.ErrorRecord]
instances; e.g.:$stdout, $stderr = ($(whoami; whoami invalidarg) 2>&1).Where({ $_ -isnot [System.Management.Automation.ErrorRecord] }, 'Split')
; you can then convert the$stderr
array to strings with$stderr = $stderr | % ToString
.2>&var
Reporting custom errors in functions and scripts:
Guidelines for when to use non-terminating errors vs. statement-terminating errors in the context of creating cmdlets are in MSDN topic Cmdlet Error Reporting; a pragmatic summary is in this Stack Overflow answer of mine.
Non-terminating errors:
Write-Error
cmdlet is designed to generate non-terminating errors; e.g.:Write-Error "Not an existing file: $_"
wraps the message in a[System.Management.Automation.ErrorRecord]
instance and outputs it to the error stream.Write-Error
currently neglects to set$?
to$False
in the caller's scope, the way a compiled cmdlet does when reporting a non-terminating error - see Write-Error in a function doesn't set automatic success variable $? to $False (doesn't set the execution status to indicate a non-terminating error) in the caller's scope PowerShell/PowerShell#3629$?
may mistakenly contain$True
even whenWrite-Error
calls were made.param()
block is decorated with the[CmdletBinding()]
attribute) - is to use the$PSCmdlet.WriteError()
method - see example below.Terminating errors:
Statement-terminating errors:
PowerShell has NO keyword- or cmdlet-based mechanism for generating a statement-terminating error.
The workaround - available in advanced functions only - is to use
$PSCmdlet.ThrowTerminatingError()
:Throw
keyword (statement), this truly only generates a statement-terminating error.On a side note: Sometimes it is desirable to terminate upstream cmdlets, without terminating the pipeline as a whole, the way
Select-Object -First <n>
does, for instance. As of Windows PowerShell v5.1 / PowerShell Core v6.0.0-beta.5, there is no way to do this, but such a feature has been suggested here: Allow user code to stop a pipeline on demand / to terminate upstream cmdlets. PowerShell/PowerShell#3821Script-terminating errors:
Throw
keyword.Catch
handler (as part of aTry
/Catch
statement), not specifying an object causes the current exception to be re-thrown.[System.Management.Automation.ErrorRecord]
, PowerShell automatically wraps the object in an instance of that type and stores the object thrown in that instance's.TargetObject
property.Example use of
$PSCmdlet.WriteError()
in an advanced function so as to create a non-terminating error (to work around the issue thatWrite-Error
doesn't set$?
to$False
in the caller's context):Example use of
$PSCmdlet.ThrowTerminatingError()
to create a statement-terminating error:The text was updated successfully, but these errors were encountered: