Never use return codes to indicate failure. People will forget to check them and you will have silent failures. It's happened to me too many times.
If I want to be able to tell which thing failed, I use Exception::Class objects. You can compare them with $@->isa('Foo'). That's much easier than trying to parse error messages to see which thing died.
If the error is not something I can handle and continue on, i.e. I just want to log it and send a friendly error page to the user, I just use Carp::croak(). Nearly all unexpected errors (like a failed database connection) are like this.