Returning the error as a second value is usually not a good idea. It requires too much discipline to always check the error status, after every call, and it doesn't allow for idiomatic checks as
foo() or die "foo failed";
so lazy programmers will just don't do it resulting on the worst kind of errors: unnoticed errors!
Usually it's much better to croak(): module users would still be able to handle errors via eval if they wish, and when not, the final user will notice that something went wrong because the croak will reach them.