I have almost never used exceptions. They really don't fit the embedded real-time systems I have been involved in.
Don't get me started. Philosophically I don't like exceptions.
The whole motivation behind exceptions is to allow one to write ones business logic, concentrate on what one likes to think ones program will do, without having lots of fiddly error checking and handling code obscuring that logic. Error situations are therefore swept under the carpet with "try" and kept out of sight with "catch".
However in my world view failure is not exceptional, it is a common happening, it's too important to be hidden away. Therefor failure handling should be in ones face in the code you write. Certainly in the face of those that read it.
Besides, so many times I have seen exceptions used for non-exceptional situations. For example I don't count failure to find a file the user has specified as exceptional, it is a regular happening. Using exceptions for handling normal behavior only obscures the code paths and makes code difficult to reason about. Totally the opposite of what they were created for.
Whenever I think about it long enough I conclude that the only truly unexpected, exceptional things that are worthy of using exceptions for are bugs in ones code or hardware failures. But then the best thing to do is die immediately rather than stagger along in an indeterminate state and causing more damage.
That is before we get into looking at performance, and behavioral determinism.
Yes, I use enums in Rust rather than special error values in return codes.