returning a non-success you either handle it or pass it up the chain, potentially with not a lot of information about what originally caused it. with an exception you can retain the full information about what happened by either rethrowing it, throwing your own exception with it embedded as the cause or declaring that you don't handle it by saying you can throw it.
I generally prefer exceptions to result codes. You can even use the mechanism to throw useful results across nested function calls.
I do prefer Maybe/Option/Either style returns in some cases though. Makes for a cleaner API.
So each method has its uses.