I would add that it's an art, and many programmers don't get it right, and what's "right" is a matter of opinion / taste. My basic stance is that low level routines should rarely, if ever, trap argument type errors, e.g., if a function expects a string and you pass it a real it should do a face plant and cause the calling function to chuck a wobbly, because that's a programming error. I see many programmers applying overly defensive strategies like this, and I think that's a mistake. However, higher level functions / procedures should trap potential errors, e.g. a function that processes csv data should anticipate that one or more fields are null or a data type not expected, because that's a potential execution error.
I acknowledge it can be a matter of taste, this was mine.
Man it's WAY to early for me to be posting. Runs off to find a coffee ...