The current error-handling system involves a global variable (CRM_Core_Error::$modeException) which switches the behavior of CRM_Core_Error::fatal() between (a) print+exit and (b) throw exception. This is a confusing arrangement (and differs from the current error-handling policies for PEAR and Symfony). To address this, we should:
1. Modify CRM_Core_Error::fatal to always throw exceptions and never abend
2. Modify CRM_Core_Invoke::invoke to catch unhandled exceptions and display the error nicely (like we do in fatal() today).
3. Introduce a coding convention for typed exceptions (eg CRM_Core_Exception extends PEAR_Exception, and it's the base-class for any new exceptions)
4. Deprecate CRM_Core_Error::fatal – errors should be reported using "throw".
Some care most be taken to ensure that exception-handling and transaction-handling work together. (This was discussed in more detail on IRC on the evening of Oct 30, 2012.)