MAJOR DISCLAIMER: I don't consider that there is a "right" answer to this. The views expressed here are subjective and personal. What's more is that the ideas I'm about to espouse are only useful if you are going to do different things with different, ahem, faults... as you might using a system as per Daniel Earwicker's informative answer. With that in mind:
I contend that "an EXCEPTION is exceptional". An ERROR is less unexpected.
disclaimer: The following pseudo-code is not good; it merely serves as the minimum case I could think of to illustrate my point.
note: in this thought experiment, GetFile returns UNDEFINED if it cannot find the specified file.
function AlwaysGetFile(name){
var file = null;
if(FileExists(name)){
file = GetFile(name);
if(typeof file === "undefined"){
throw new "couldn't retrieve file" EXCEPTION
}
}
else{
throw new "file does not exist" ERROR
}
return file;
}
In the case that a consumer calls GetFileOrThrow with a filename that doesn't exist, an ERROR will occur. To my mind the distinction is really that higher-level code (or user input) is doing something wrong... this function must pass an ERROR up the line to that higher-level code which can decide what to do about this result. Consider it like this... this function would be saying to any consuming functions:
Look, my friend, I know what's going on here: it is an ERROR to request BobAccounts.xml, so don't do it again! Oh, and if you think you now know what might have gone wrong (having abused me), go ahead and try to recover from it!
Now consider the case that this function takes the name, checks that the file exists and then for some reason fails to retrieve it. This is a different situation. Something really unexpected has happened. What's more, the consuming code isn't to blame. Now we really want this function to say to any consuming functions:
Oh fiddlesticks! Sorry about this, I humbly beg your pardon but something EXCEPTIONAL that I don't really understand has gone wrong. I don't think that your request for BobAccounts.xml was unreasonable... and I know I should be fulfilling it for you. Since I'm lower level code than you, I really ought to know what's going on... but I don't... and since you've less chance than me of understanding this EXCEPTIONAL situation, I think you'd probably best just stop what you're doing and let this message go all the way to the top... I mean, there is something seriously fishy going on here.
So I suppose my summary is this: If the mistake happened in higher order code (you were passed bad data) throw an ERROR. If the mistake happened in lower order code (a function you depended on failed in a way you didn't understand and couldn't plan for) throw an EXCEPTION... and if the mistake happened in the function you are currently writing... well, duh, if you're aware of it then fix it!
And, finally, to answer the original question more directly: In terms of handling ERRORS and EXCEPTIONS, my advice would be: Handle all ERRORS gracefully (optionally logging them)... but handle EXCEPTIONS carefully indeed; only try to recover from an EXCEPTION if you are really sure you know what it is and why it's happened, otherwise let it bubble up (rethrowing it if you have to).