My view on exceptions versus return values is that they provide the same information, but with different default actions:

When communicating success or failure using a return value, the 'default action' is to ignore the failure.

When communicating success or failure using exceptions, the 'default action' is to abort the program.

We commonly convert between return values and exceptions, with eval {} and or die "..." being the most commonly seen transformations.

Given that any manipulation of privileges implies that work is being done in a security sensitive context, I feel that the only sensible course of action is to throw an exception should an operation fail. A program that wishes to handle such an event can easily catch the exception and do so.

The croaks in the XS code definitely need to be standardised to more easily allow for exception handling to occur, and it's my intention to have this done and the exceptions well documented before the module is released in a more stable form.