I have often seen variations of @alextremblay’s approach where pair of values is returned. The first one is just an error/result flag or an exit code (e.g. system call like with 0 means success, everything else marks a failure) or similar to protocols like HTTP, SMTP etc. (2XX success, 4XX transient error (you might want to try again), 5XX permanent error). The second value is then either the result or the error message.