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: