Search code examples
powershellerror-handlingpowershell-core

How to throw a catchable error that displays concisely


I'd like to throw an error from a custom cmdlet that

  1. Is script-terminating, causing any script it is part of to terminate (unless caught)
  2. Displays concisely if shown in a terminal, without a stack trace

So far I have tried:

Description (with screenshot) Script-terminating Concise Catchable
throw statement on a naked string. ✅ Yes ❌ No ✅ Yes
The $PSCmdlet.ThrowTerminatingError method. ❌ No ✅ Yes ✅ Yes
The Write-Error cmdlet. ❌ No (nor statement-terminating) ✅ Yes ❌ No

Note that my cmdlet should be usable from scripts not controlled by me too - that is, the behavior shouldn't require setting preference variables if doing so would affect the running script.

Is there any way to throw a concise/informative error from a cmdlet?


Solution

  • The only way for a throw statement to generate a single-line error message without a location message - assuming that the $ErrorView preference variable is at its (PowerShell (Core)) default, 'Concise' - is:

    • You must be running PowerShell (Core) 7+ (as your tags incidate) rather than the legacy Windows PowerShell edition...

    • ... and the (cmdlet-like) function that uses throw must originate from a (persisted)[1] PowerShell module.

    Caveats:

    • Unlike when you use $PSCmdlet.ThrowTerminatingError() (which only generates a statement-terminating error, however), the exception message will be prefixed generically with Exception: rather than the function name.
      This applies up to at least PowerShell 7.3.7 (current as of this writing).

    • By using throw, your cmdlet-like function will exhibit nonstandard behavior, given that binary cmdlets (those compiled into .NET assemblies) can not generate script-terminating errors, only statement-terminating ones.


    [1] Curiously, this does not apply to dynamic modules created via New-Module