> then all of my carefully crafted error-handling routines would go up in flames
No just sandbox the code inside a try catch...
> pattern matching is the best method of clearly displaying intents and possible downfalls.
You are stating an opinions as a fact here.
This works fine if it's just a matter of rolling back a database transaction or releasing file handles (b/c someone else is doing all the work for you). But if you have more complicated invariants, your try catch has to handle restoring those invariants, no matter what path your code took.
The most important feature is that catch blocks are executed before the stack is unwond, providing the ability for a handler to signal back to the context where the error occurred how it should be handled.
It's sad that no other languages implement this and instead simply decide that exceptions are bad.
The code expander has an entry point which allows the caller to be informed about what variables and functions are free in a block of code. The implementation of this entry point works by intercepting warning exceptions about unbound symbols, and accumulating them in in lists, which are then returned to the caller.
This is a useful thing which reduces the need for users to write their own code walker in certain kinds of advanced macros.
This sounds like a general errors handling issue that nor exceptions nor monadic errors types can prevent.
* panic + catch_unwind, but that's special and not meant or used in practice for error handling