When you start thinking about every function having multiple return values, one of which is an error optional, treat every one of those function as failable, and then build that functionality into the compiler - then you soon arrive at proper exceptions. Granted, forcing the error machinery syntax upon the programmer makes it more explicit and requires less discipline, but it also gets old pretty fast.
Yes. Exception is generally a decent solution to error handling unless you're using RAII languages like C++/Rust where unwinding the stack doesn't work well with destructors.