After reading this article I have yet another idea how to handle errors. A caller should provide two return addresses for a calle - one for normal return and another one for error return. Doing so isn't particularly costly - it requires pushing an error-handler block address before the call instruction and popping it after. It should be easier compared to unwinding, since no side-tables are necessary and thus going the error path shouldn't be substantially costly compared to the happy path.
The nice thing about this convention is that the error return address can be modeled in earlier versions of the API/ABI simply as an extra parameter - technically a continuation that the function tailcalls into; this is extensible to any return of enum-like data, not just error values.