As a general rule, I throw exceptions from:
- public functions of a package to catch programming errors.
- internal functions to report system errors or pass-through sub-system errors.
where I use asserts only internally to catch implementation mistakes.