I agree that a database API should not itself throw an error if an empty result set is found. It may throw an error if there is an SQL error, though, and really should. When one gets an empty result set where this should not happen, for instance because a row was just inserted and one is in a transaction, the user code could throw an exception instead.
Making exceptions optional is something that I have indeed done in the past because some uses of the code could benefit from exceptions while other uses did not so much.
Some things are essential to the page we are rendering, and if they are missing we should 404.
Some things are ancillary, and if they are missing we should render a stub in their place. E.g., saying that a comment is from "deleted user".
Exceptions are a good fit for the former, where we want to unify every failure. They are a poor choice for the other case, where we want to treat each failure special.
Which case a given fetch represents is a choice that should be driven by the fetcher.
They have a type, make it say MissingUserException and the special place can handle it in a special way. Ensure it is a subclass of some general exception type you also handle elsewhere and you're good.
Often people throw generic exceptions instead of using the type system.