Returning appropriate data structure representing a possible failure (a Future, a Try, an Either and so on) is always preferable than throwing exceptions in the wild. It will inform the caller about the possibility of a failure, and it will force them to manage it.

Exceptions should only be thrown for unrecoverable errors, such as hardware failures and similar.