I would argue that in the majority of the cases that's the only reasonable behavior. I do agree that errors should be handled as close as possible to where they occured, but not any closer -- e.g. there is not much you can do within a library's functions if an unexpected error occured inside. It should be handled at whatever business code happens to call it. And in the worst case, they should bubble up to a central handler, that either outputs an 500 error, or an error dialog.
Exceptions pretty much make this the sane/default behavior, with rust-like ADTs with syntax sugar being close.
Exceptions pretty much make this the sane/default behavior, with rust-like ADTs with syntax sugar being close.