How impossible are we talking?

I tend to be a fairly defensive programmer - maybe nothing currently sends this function a negative value, but how hard is it for a future code change to alter that assumption? I always figured a clear error was best. It lets even someone unfamiliar with the code know what assumptions are being made about the valid range of inputs, so they don't have to consider impossible outliers.

Obviously it isn’t totally impossible, but it becomes challenging to know if it’s required or not. It’s hardest when it isn’t just throwing an error but instead defaulting to something only half-sensible. For example replacing a negative number with 0 or overflowing rather than panicking.

When it comes to assumptions about the input, ideally model them in the type system. If you can’t, explicit checks and throws are OK in my book. But don’t check-and-hide any errors. You’ll be hard pressed to debug the issues they’ll cause down the road, since it will usually be far from the implementation that you see the impact.