Hello,
A controlled error is an exception too and it is better to create controlled exceptions than to return error codes. The code remains cleaner and you can see the intentionality.
Filling the code with error constants is not a good practice either. I think in the middle is the right thing
Thank you for the comment