Don't let reporting a failed parallel worker abort the rest of the run - #3004
Merged
Conversation
Invoke-InRunspacePool reports a worker that threw with Write-Error and keeps going, the remaining files still have results worth reporting. Write-Error obeys the caller's $ErrorActionPreference though, so a caller running with 'Stop', which is what a CI script typically does, gets a terminating error instead and the loop aborts on the first failing file, dropping the results of everything that already finished. Both Write-Error calls are now explicitly -ErrorAction Continue. Pester's own test.ps1 sets 'Stop' on line 43, so this reliably killed the P phase locally and with it the whole RSpec phase after it. Also widens two timing assertions. Both bound the measured time from above, and measuring a scriptblock times compiling it, GC, and whatever else the machine is doing, which has no upper bound on a shared runner. "Does not throw when actual is faster than expected" failed on macOS on two PRs today. A 10ms sleep that takes 30 seconds means the machine is broken, not that the assertion is wrong. The opposite direction needs no margin, a sleep never finishes early. 🤖
This was referenced Aug 24, 2026
nohwnd
added a commit
that referenced
this pull request
Aug 24, 2026
Four files went into a Run.Parallel run on CI and three came back. The missing file was not failed, skipped or errored, it was not reported at all, and the run looked green with one test fewer than it should have had. Invoke-TestInParallel filters worker results with a Where-Object that keeps only well formed result objects, to guard against stray pipeline output. That filter cannot tell stray output from a worker that died before returning its result, and nothing afterwards compared the number of results to the number of files sent. So a lost file was dropped as quietly as a stray string, and Sort-Object put the survivors in discovery order, which made the output look like a normal shorter run. Compare the counts after the filter and throw, naming the files that went missing. The worker's own error is already surfaced by Invoke-InRunspacePool, this says which file it cost us. Losing results silently is worse than failing. This is independent of why the worker died. Any worker that dies for any reason costs a whole test file, and #3004 only stopped one failing worker from aborting the results of the others. Added a test that hands Invoke-TestInParallel a runspace pool runner which drops one file's result, and asserts the run throws and names that file. Fix #3011 🤖
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two flaky tests, one of which turned out to be a real bug in
Run.Parallel.Reporting a failed worker aborted the run
Invoke-InRunspacePoolreports a worker that threw withWrite-Errorand keeps going, because the remaining files still have results worth reporting.Write-Errorobeys the caller's$ErrorActionPreferencethough, so a caller running withStopgets a terminating error instead, the loop aborts on the first failing file, and the results of everything that already finished are dropped. CI scripts commonly run withStop.Both
Write-Errorcalls are now explicitly-ErrorAction Continue, with a test that setsStopitself so it stays fixed regardless of the harness.Pester's own
test.ps1setsStopon line 43, so this reliably killed the P phase locally and with it the entire RSpec phase after it. With the fix the full local suite completes: 2915 passed, 0 failed, 3 skipped.Timing assertions
Should-BeFasterThan.Does not throw when actual is faster than expectedfailed onPS7 - macOS lateston both #2993 and #2995 today and needed manual reruns.Both flaky assertions bound the measured time from above, and measuring a scriptblock times compiling it, GC, and whatever else the machine is doing, which has no upper bound on a shared runner. Widened both from
100ms/1000msto30s, with a comment recording the asymmetry so they do not get tightened again: a 10ms sleep that takes 30 seconds means the machine is broken, and the opposite direction needs no margin because a sleep never finishes early.🤖