Can someone who uses exceptions in large systems offer a comment on <i>which</i> exceptions they throw?<p>One of the problems I have in trying to design with exceptions is that they seem to offer a lot of potential to break abstraction layers.<p>As a concrete example, if you have a cacheing layer which - say - is implemented over the filesystem. In the event of an inability to access the correct location, the low-level routines might throw a permission-related exception. If you swap out the filesystem cacheing implementation with, say, one based on memcached you might instead get a network-related exception.<p>Neither of these types really make sense in the context of a 'cacheing layer error', they seem to leak implementation details - breaking the abstraction.<p>Do people accept this, or do they catch-and-rethrow new exception types at major layer boundaries? (e.g. in the above two implementations, both low-level exceptions may be caught and rethrown as "CacheInitialisationError" with some perhaps some additional diagnostic about the underlying cause). If they have such API-specific error types, do you go to the trouble of modelling an exception type hierarchy? So all your 'cache layer' exceptions inherit from 'CacheError' so a higher level can catch all "CacheExceptions" in one place? This seems like a lot of additional modelling effort, is it commonplace?<p>To my mind, the possible exceptions a API call may make (or equivalently, the errors it could return) are <i>part</i> of the API, and the errors need to be at the same conceptual level as the rest of the API. (So you can't have filesystem errors in a generic cache API).<p>What happens in practice?