Skip to content

Commit 8eef0bf

Browse files
Copilotjohlju
andcommitted
Correct ErrorActionPreference guidance based on testing
Co-authored-by: johlju <[email protected]>
1 parent 2d01ca3 commit 8eef0bf

File tree

1 file changed

+33
-13
lines changed

1 file changed

+33
-13
lines changed

CONTRIBUTING.md

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,8 @@ commands are located in the folder `./source/Public`.
313313
Public commands should primarily use `Write-Error` for error handling, as it
314314
provides the most flexible and predictable behavior for callers. The statement
315315
`throw` shall never be used in public commands except within parameter
316-
validation attributes like `[ValidateScript()]` where it is the only option.
316+
validation attributes like `[ValidateScript()]` where it is the only valid
317+
mechanism for validation failures.
317318

318319
##### When to Use Write-Error
319320

@@ -411,8 +412,12 @@ Use `$PSCmdlet.ThrowTerminatingError()` only in these limited scenarios:
411412
is well understood
412413
2. **Assert-style commands** (like `Assert-SqlDscLogin`) whose purpose is to
413414
throw on failure
414-
3. **Commands with `SupportsShouldProcess`** where an error in the
415-
`ShouldProcess` block must terminate (before state changes)
415+
3. **Commands with `SupportsShouldProcess`** where an operation failure in the
416+
`ShouldProcess` block must terminate (common for state-changing operations
417+
that cannot be partially completed)
418+
4. **Catch blocks in state-changing commands** where a critical operation
419+
failure must be communicated as a terminating error to prevent further
420+
state changes
416421

417422
In these cases, ensure callers are aware of the behavior and use
418423
`-ErrorAction 'Stop'` when calling the command from other commands.
@@ -434,9 +439,13 @@ how exceptions are caught:
434439

435440
**Recommended pattern for .NET methods:**
436441

437-
This example shows using `$PSCmdlet.ThrowTerminatingError()` in a catch block,
438-
which is acceptable when catching exceptions from .NET methods. The caller must
439-
use `-ErrorAction 'Stop'` to catch this error.
442+
This example shows a state-changing command using `$PSCmdlet.ThrowTerminatingError()`
443+
in a catch block. This is acceptable for commands with `SupportsShouldProcess` where
444+
operation failures must terminate. Note that callers must use `-ErrorAction 'Stop'`
445+
to catch this error.
446+
447+
For non-state-changing commands (like Get/Test commands), prefer `Write-Error` in
448+
catch blocks instead.
440449

441450
```powershell
442451
try
@@ -461,10 +470,10 @@ catch
461470
}
462471
```
463472

464-
**Pattern for cmdlets with blanket error handling:**
473+
**Pattern for blanket error handling:**
465474

466-
Only use `$ErrorActionPreference = 'Stop'` when you have multiple cmdlets
467-
and don't want to add `-ErrorAction 'Stop'` to each one:
475+
Use `$ErrorActionPreference = 'Stop'` when you need blanket error handling for
476+
multiple cmdlets or when calling commands that use `$PSCmdlet.ThrowTerminatingError()`:
468477

469478
```powershell
470479
try
@@ -487,6 +496,12 @@ finally
487496
}
488497
```
489498

499+
> [!NOTE]
500+
> Setting `$ErrorActionPreference = 'Stop'` is particularly useful when calling
501+
> commands that use `$PSCmdlet.ThrowTerminatingError()`. Without it (or
502+
> `-ErrorAction 'Stop'` on each call), these command-terminating errors will not
503+
> stop the calling function - it will continue executing after the error.
504+
490505
> [!IMPORTANT]
491506
> **Do not** use the pattern `$ErrorActionPreference = 'Stop'` followed by
492507
> `-ErrorAction 'Stop'` on the same cmdlet - this is redundant. The
@@ -495,9 +510,12 @@ finally
495510
496511
> [!NOTE]
497512
> The pattern of setting `$ErrorActionPreference = 'Stop'` in a try block
498-
> with restoration in finally is useful for blanket error handling, but NOT
499-
> necessary for .NET method calls (they always throw) or when using
500-
> `-ErrorAction 'Stop'` on individual cmdlets.
513+
> with restoration in finally is useful for:
514+
> - Blanket error handling across multiple cmdlets
515+
> - Catching errors from commands that use `$PSCmdlet.ThrowTerminatingError()`
516+
> (without this, those errors won't stop the caller)
517+
> - However, it's NOT necessary for .NET method calls (they always throw) or
518+
> when using `-ErrorAction 'Stop'` on individual cmdlets.
501519
502520
##### Parameter Validation with ValidateScript
503521

@@ -582,9 +600,11 @@ $results = $items | Process-Items -ErrorAction 'Stop'
582600
| General error handling in public commands | `Write-Error` | Provides consistent, predictable behavior; allows caller to control termination |
583601
| Pipeline processing with multiple items | `Write-Error` | Allows processing to continue for remaining items |
584602
| Catching .NET method exceptions | try-catch without setting `$ErrorActionPreference` | .NET exceptions are always caught automatically |
585-
| Blanket error handling for multiple cmdlets | Set `$ErrorActionPreference = 'Stop'` in try, restore in finally | Avoids adding `-ErrorAction 'Stop'` to each cmdlet |
603+
| Blanket error handling for multiple cmdlets | Set `$ErrorActionPreference = 'Stop'` in try, restore in finally | Avoids adding `-ErrorAction 'Stop'` to each cmdlet; also catches ThrowTerminatingError from child commands |
586604
| Single cmdlet error handling | Use `-ErrorAction 'Stop'` on the cmdlet | Simpler and more explicit than setting `$ErrorActionPreference` |
605+
| Calling commands that use ThrowTerminatingError | Set `$ErrorActionPreference = 'Stop'` or use `-ErrorAction 'Stop'` | Required to catch these command-terminating errors; without it, caller continues after error |
587606
| Assert-style commands | `$PSCmdlet.ThrowTerminatingError()` | Command purpose is to throw on failure |
607+
| State-changing commands (catch blocks) | `$PSCmdlet.ThrowTerminatingError()` | Prevents partial state changes; caller must use `-ErrorAction 'Stop'` or set `$ErrorActionPreference` |
588608
| Private functions (internal use only) | `$PSCmdlet.ThrowTerminatingError()` or `Write-Error` | Behavior is understood by internal callers |
589609
| Parameter validation in `[ValidateScript()]` | `throw` | Only valid option within validation attributes |
590610
| Any other scenario in commands | Never use `throw` | Poor error messages; unpredictable behavior |

0 commit comments

Comments
 (0)