Errors Travel in the Opposite Direction

by Jan 2, 2013

Here's a piece of code for you to wrap your head around:

1..10 | 
  ForEach-Object { trap { Write-Host "Phew: $_" continue } $_ } | 
  ForEach-Object { if ($_ -gt 4) { Throw "Too big!" } else { $_ } }

Ten numbers are fed into the pipeline. They reach the downstream cmdlet ForEach-Object which basically only implements an error handler (trap) and then passes the number on to the next downstream cmdlet which happens to be another ForEach-Object.

The second ForEach-Object checks the number, and if it is greater than 4, it throws an error.

Pipelines usually work strictly downstream, so if something happens in a downstream cmdlet, upstream cmdlets won't notice. Errors (exceptions), however, travel the opposite direction, so when you run the code, this is the result:

1
2
3
4
Phew: Too big!
Phew: Too big!
Phew: Too big!
(...)

Although the second ForEach-Object encountered some special situation, it is the first (upstream) cmdlet that responds to it.

This basically enables you to establish an inner-pipeline-communication-system where a downstream cmdlet can tell an upstream cmdlet: "I've had enough"! Coincidentally, this is how PowerShell 3.0 implemented Select-Object with its parameter -First. Once the first x elements are received, upstream cmdlets stop.

Twitter This Tip! ReTweet this Tip!