I agree that the error handling is terrible, but I'm not sure how much better it could be without generics.
For me, the gold standard in error handling is Rust, where the type system simply does not allow you to ignore errors. This means that the existence of error handling is checked at compile time. Of course, this doesn't mean your error handling is _good_, but I think that's beyond any language design to enforce.
But the Rust system is entirely built around a generic Result type, where both the non-error result (an int, string, struct, etc.) _and_ the error type itself are both generic.