> If they propagate down the stack then you lose context. You also may not have all the data you need to properly recover (e.g. still write to a table but make the errored field null).
By "context" I mean other data that lived at the time of the error. For example, you may want to update a table row when there's an error but if a thrown error takes you too far down the stack then you might not know the row ID anymore
Then you have built your program incorrectly and not caught the error in a place where you still have context (e. g. `YourProgramException` sub-type that indicates a recoverable error or `Exception` in the case that you're building something where it doesn't matter what the error is, just that an error occurred).
This can also be done with error passing, and is a design failure there too:
_, ex = perform_batch_operation(on: list_of_data)
if ex:
# Oh no, we don't know which entry in the list failed
# and can't update the appropriate row
# (This, of course, should be handled in
# perform_batch_operation, not bubbled up here)