In my experience, the vast majority of the time the best (or only) way to correctly deal with the error is to propagate it up the stack. Making this optional (having to explicitly check return values) doesn't make it more likely to be done.
i wish people understood this thinking about and handling all errors, as a prime functiom of the code, is why things like Linux and C Python and X server and git and so on are so reliable.
they are successful in spite of the memory unsafety of C because of the culture that the behavior of a failing system is a principle feature of the code, which is common thinking in C and easier to do when you don't have the crutch of exceptions.
_how_ you deal with that failure is a separate question
but it's critical that every fallible expression explicitly and visibly demonstrates the possibility of failure
this is in no way an "error handling mess" -- on the contrary, it is basically the only way to produce robust and reliable software at scale