Hello!
I like my code to stop on errors, not continue past them. For example, if a script fails to enable logs for my app I want to know right away. I don’t want to find out tomorrow when I need logs that aren’t there. The earlier I know about errors, the better. I learned this as the Fail Early Fail Often pattern.
PowerShell has a dedicated type of error that’s non-terminating. Its default is to continue past them. That applies in DSC configurations, too.
We can see this with a simple DSC configuration and the Write-Error
command in a Script resource:
Configuration Headless { Import-DscResource -ModuleName PSDesiredStateConfiguration Node 'localhost' { Log Before { Message = 'Before error.' } Script NonTerminatingError { GetScript = {@{Result = ''}} SetScript = {Write-Error 'Non-terminating error.'} TestScript = {Return $false} } Log After { Message = 'After error.' } } } Headless -ConfigurationData $ConfigurationData Start-DscConfiguration -Wait -Force -Verbose -Path '.\Headless\'
The middle resource generates an error but the last resource still runs:
... VERBOSE: [VAGRANT]: [[Log]Before] Before error. VERBOSE: [VAGRANT]: LCM: [ End Set ] [[Log]Before] in 0.0000 seconds. VERBOSE: [VAGRANT]: LCM: [ End Resource ] [[Log]Before] VERBOSE: [VAGRANT]: LCM: [ Start Resource ] [[Script]NonTerminatingError] VERBOSE: [VAGRANT]: LCM: [ Start Test ] [[Script]NonTerminatingError] VERBOSE: [VAGRANT]: LCM: [ End Test ] [[Script]NonTerminatingError] in 0.0780 seconds. VERBOSE: [VAGRANT]: LCM: [ Start Set ] [[Script]NonTerminatingError] VERBOSE: [VAGRANT]: [[Script]NonTerminatingError] Performing the operation "Set-TargetResource" on target "Executing the SetScript with the user supplied credential". VERBOSE: [VAGRANT]: LCM: [ End Set ] [[Script]NonTerminatingError] in 0.0470 seconds. VERBOSE: [VAGRANT]: LCM: [ Start Resource ] [[Log]After] VERBOSE: [VAGRANT]: LCM: [ Start Test ] [[Log]After] VERBOSE: [VAGRANT]: LCM: [ End Test ] [[Log]After] in 0.0000 seconds. VERBOSE: [VAGRANT]: LCM: [ Start Set ] [[Log]After] VERBOSE: [VAGRANT]: [[Log]After] After error. ...
We can tell DSC to stop on non-terminating errors by passing the ErrorAction
flag when we start our configuration:
Start-DscConfiguration -Wait -Force -Verbose -ErrorAction 'Stop' -Path '.\Headless\'
Now it stops on the Write-Error
:
VERBOSE: [VAGRANT]: [[Log]Before] Before error. VERBOSE: [VAGRANT]: LCM: [ End Set ] [[Log]Before] in 0.0000 seconds. VERBOSE: [VAGRANT]: LCM: [ End Resource ] [[Log]Before] VERBOSE: [VAGRANT]: LCM: [ Start Resource ] [[Script]NonTerminatingError] VERBOSE: [VAGRANT]: LCM: [ Start Test ] [[Script]NonTerminatingError] VERBOSE: [VAGRANT]: LCM: [ End Test ] [[Script]NonTerminatingError] in 0.0780 seconds. VERBOSE: [VAGRANT]: LCM: [ Start Set ] [[Script]NonTerminatingError] VERBOSE: [VAGRANT]: [[Script]NonTerminatingError] Performing the operation "Set-TargetResource" on target "Executing the SetScript with the user supplied credential". Stderr from the command: powershell.exe : Non-terminating error.
There’s also an $ErrorActionPreference
variable, but that didn’t work no matter where I set it. The ErrorAction
flag seems to be the way.
This isn’t necessarily a best practice, the PowerShell default is to continue past errors, but I usually have a better life if I switch it to stop.
Happy automating!
Adam
Need more than just this article? We’re available to consult.
You might also want to check out these related articles: