diff --git a/CRM/Contact/BAO/Contact.php b/CRM/Contact/BAO/Contact.php
index 5122ec5079aeb324b5961b0545dd363473d30e62..e27e551f52978f4292cffc9a79519c5cefbcc334 100644
--- a/CRM/Contact/BAO/Contact.php
+++ b/CRM/Contact/BAO/Contact.php
@@ -101,7 +101,7 @@ class CRM_Contact_BAO_Contact extends CRM_Contact_DAO_Contact {
    * @return CRM_Contact_DAO_Contact|CRM_Core_Error|NULL
    *   Created or updated contact object or error object.
    *   (error objects are being phased out in favour of exceptions)
-   * @throws \Exception
+   * @throws \CRM_Core_Exception
    */
   public static function add(&$params) {
     $contact = new CRM_Contact_DAO_Contact();
@@ -1320,7 +1320,7 @@ WHERE     civicrm_contact.id = " . CRM_Utils_Type::escape($id, 'Integer');
       return $contactTypes;
     }
     else {
-      CRM_Core_Error::fatal();
+      throw new CRM_Core_Exception();
     }
   }
 
@@ -2017,7 +2017,7 @@ ORDER BY civicrm_email.is_primary DESC";
     }
 
     if (empty($contactID)) {
-      CRM_Core_Error::fatal('Cannot proceed without a valid contact id');
+      throw new CRM_Core_Exception('Cannot proceed without a valid contact id');
     }
 
     // Process group and tag
diff --git a/CRM/Contact/Form/Search/Custom.php b/CRM/Contact/Form/Search/Custom.php
index dbfb6165f2f69a906c077825ae126b53cf3de885..cfc78ef8355b7a73c972547c30a25363667a4d91 100644
--- a/CRM/Contact/Form/Search/Custom.php
+++ b/CRM/Contact/Form/Search/Custom.php
@@ -34,7 +34,7 @@ class CRM_Contact_Form_Search_Custom extends CRM_Contact_Form_Search {
       ) = CRM_Contact_BAO_SearchCustom::details($csID, $ssID, $gID);
 
     if (!$this->_customSearchID) {
-      CRM_Core_Error::fatal('Could not get details for custom search.');
+      CRM_Core_Error::statusbounce('Could not get details for custom search.');
     }
 
     // stash this as a hidden element so we can potentially go there if the session
diff --git a/CRM/Contact/Form/Search/Custom/Base.php b/CRM/Contact/Form/Search/Custom/Base.php
index 25bed0be962c37aecb4a1f502ace9a81cc5411ac..43e59d3ff15ab79337ded785cc30a51a36f9311f 100644
--- a/CRM/Contact/Form/Search/Custom/Base.php
+++ b/CRM/Contact/Form/Search/Custom/Base.php
@@ -193,7 +193,7 @@ class CRM_Contact_Form_Search_Custom_Base {
 
     foreach ($includeStrings as $string) {
       if (stripos($sql, $string) === FALSE) {
-        CRM_Core_Error::fatal(ts('Could not find \'%1\' string in SQL clause.',
+        CRM_Core_Error::statusBounce(ts('Could not find \'%1\' string in SQL clause.',
           [1 => $string]
         ));
       }
@@ -201,7 +201,7 @@ class CRM_Contact_Form_Search_Custom_Base {
 
     foreach ($excludeStrings as $string) {
       if (preg_match('/(\s' . $string . ')|(' . $string . '\s)/i', $sql)) {
-        CRM_Core_Error::fatal(ts('Found illegal \'%1\' string in SQL clause.',
+        CRM_Core_Error::statusBounce(ts('Found illegal \'%1\' string in SQL clause.',
           [1 => $string]
         ));
       }
diff --git a/CRM/Contact/Form/Search/Custom/Group.php b/CRM/Contact/Form/Search/Custom/Group.php
index b6e4d59d645193e034ac92f847d0f5cb08ac7630..502d041820df01e155eb008b70a86cdc31affdbf 100644
--- a/CRM/Contact/Form/Search/Custom/Group.php
+++ b/CRM/Contact/Form/Search/Custom/Group.php
@@ -329,7 +329,7 @@ class CRM_Contact_Form_Search_Custom_Group extends CRM_Contact_Form_Search_Custo
             $ssGroup = new CRM_Contact_DAO_Group();
             $ssGroup->id = $values;
             if (!$ssGroup->find(TRUE)) {
-              CRM_Core_Error::fatal();
+              CRM_Core_Error::statusBounce(ts('Smart group sepecifed in exclude groups is not found in the database'));
             }
             CRM_Contact_BAO_GroupContactCache::load($ssGroup);
 
@@ -389,7 +389,7 @@ WHERE  gcc.group_id = {$ssGroup->id}
           $ssGroup = new CRM_Contact_DAO_Group();
           $ssGroup->id = $values;
           if (!$ssGroup->find(TRUE)) {
-            CRM_Core_Error::fatal();
+            CRM_Core_Error::statusBounce(ts('Smart group sepecifed in include groups is not found in the database'));
           }
           CRM_Contact_BAO_GroupContactCache::load($ssGroup);
 
diff --git a/CRM/Contact/Form/Search/Custom/PriceSet.php b/CRM/Contact/Form/Search/Custom/PriceSet.php
index 56f5c5e53c387cbf63afe1f4cb8f6206e186d0cc..327bc9004502be2787411fa46fa4ad8af9dc7b5b 100644
--- a/CRM/Contact/Form/Search/Custom/PriceSet.php
+++ b/CRM/Contact/Form/Search/Custom/PriceSet.php
@@ -185,7 +185,7 @@ AND    p.entity_id    = e.id
     }
 
     if (empty($event)) {
-      CRM_Core_Error::fatal(ts('There are no events with Price Sets'));
+      CRM_Core_Error::statusBounce(ts('There are no events with Price Sets'));
     }
 
     $form->add('select',
diff --git a/CRM/Contact/Form/Task/Batch.php b/CRM/Contact/Form/Task/Batch.php
index 65a7a873153e53b16b587170d4ec3f063f18837c..c213001a72ee04b8e5b1762e0b708a19b022881a 100644
--- a/CRM/Contact/Form/Task/Batch.php
+++ b/CRM/Contact/Form/Task/Batch.php
@@ -66,7 +66,7 @@ class CRM_Contact_Form_Task_Batch extends CRM_Contact_Form_Task {
     $ufGroupId = $this->get('ufGroupId');
 
     if (!$ufGroupId) {
-      CRM_Core_Error::fatal('ufGroupId is missing');
+      CRM_Core_Error::statusBounce(ts('ufGroupId is missing'));
     }
     $this->_title = ts('Update multiple contacts') . ' - ' . CRM_Core_BAO_UFGroup::getTitle($ufGroupId);
     CRM_Utils_System::setTitle($this->_title);
diff --git a/CRM/Contact/Form/Task/Delete.php b/CRM/Contact/Form/Task/Delete.php
index 5b2b088003076a6e33b31c5e16f0f2c15ce58aec..a4996b227f5e42c010aa6959b58e9d11636d401f 100644
--- a/CRM/Contact/Form/Task/Delete.php
+++ b/CRM/Contact/Form/Task/Delete.php
@@ -68,10 +68,10 @@ class CRM_Contact_Form_Task_Delete extends CRM_Contact_Form_Task {
 
     if ($cid) {
       if (!CRM_Contact_BAO_Contact_Permission::allow($cid, CRM_Core_Permission::EDIT)) {
-        CRM_Core_Error::fatal(ts('You do not have permission to delete this contact. Note: you can delete contacts if you can edit them.'));
+        CRM_Core_Error::statusBounce(ts('You do not have permission to delete this contact. Note: you can delete contacts if you can edit them.'));
       }
       elseif (CRM_Contact_BAO_Contact::checkDomainContact($cid)) {
-        CRM_Core_Error::fatal(ts('This contact is a special one for the contact information associated with the CiviCRM installation for this domain. No one is allowed to delete it because the information is used for special system purposes.'));
+        CRM_Core_Error::statusBounce(ts('This contact is a special one for the contact information associated with the CiviCRM installation for this domain. No one is allowed to delete it because the information is used for special system purposes.'));
       }
 
       $this->_contactIds = [$cid];
diff --git a/CRM/Contact/Form/Task/Map.php b/CRM/Contact/Form/Task/Map.php
index d9f1d339c95ec9238447cc56c6086355eb830fc9..82b79608378261dd9b4ccbc77c93754f4f75804f 100644
--- a/CRM/Contact/Form/Task/Map.php
+++ b/CRM/Contact/Form/Task/Map.php
@@ -58,7 +58,7 @@ class CRM_Contact_Form_Task_Map extends CRM_Contact_Form_Task {
         // CRM-11766
         $profileIDs = CRM_Profile_Page_Listings::getProfileContact($profileGID);
         if (!in_array($cid, $profileIDs)) {
-          CRM_Core_Error::fatal();
+          CRM_Core_Error::statusBounce(ts('Contact not found when building list of contacts in the profile'));
         }
       }
       elseif ($context) {
diff --git a/CRM/Contact/Import/ImportJob.php b/CRM/Contact/Import/ImportJob.php
index 1605ebcd6388fb869752d3194075d4d94ed1fa16..043918db222c4a4198c8b9adfe1ecd11ec0a44b1 100644
--- a/CRM/Contact/Import/ImportJob.php
+++ b/CRM/Contact/Import/ImportJob.php
@@ -52,7 +52,7 @@ class CRM_Contact_Import_ImportJob {
    * @param null $createSql
    * @param bool $createTable
    *
-   * @throws Exception
+   * @throws \CRM_Core_Exception
    */
   public function __construct($tableName = NULL, $createSql = NULL, $createTable = FALSE) {
     $dao = new CRM_Core_DAO();
@@ -60,7 +60,7 @@ class CRM_Contact_Import_ImportJob {
 
     if ($createTable) {
       if (!$createSql) {
-        CRM_Core_Error::fatal('Either an existing table name or an SQL query to build one are required');
+        throw new CRM_Core_Exception(ts('Either an existing table name or an SQL query to build one are required'));
       }
 
       // FIXME: we should regen this table's name if it exists rather than drop it
@@ -72,7 +72,7 @@ class CRM_Contact_Import_ImportJob {
     }
 
     if (!$tableName) {
-      CRM_Core_Error::fatal('Import Table is required.');
+      throw new CRM_Core_Exception(ts('Import Table is required.'));
     }
 
     $this->_tableName = $tableName;
diff --git a/CRM/Core/Payment/Elavon.php b/CRM/Core/Payment/Elavon.php
index 71ca4d5af1dd2065894cccd68aaa9c2f6b3a94e9..0e63ded17d12c56d104a100e945a99ce45cbda74 100644
--- a/CRM/Core/Payment/Elavon.php
+++ b/CRM/Core/Payment/Elavon.php
@@ -120,11 +120,11 @@ class CRM_Core_Payment_Elavon extends CRM_Core_Payment {
    */
   public function doDirectPayment(&$params) {
     if (isset($params['is_recur']) && $params['is_recur'] == TRUE) {
-      CRM_Core_Error::fatal(ts('Elavon - recurring payments not implemented'));
+      throw new CRM_Core_Exception(ts('Elavon - recurring payments not implemented'));
     }
 
     if (!defined('CURLOPT_SSLCERT')) {
-      CRM_Core_Error::fatal(ts('Elavon / Nova Virtual Merchant Gateway requires curl with SSL support'));
+      throw new CRM_Core_Exception(ts('Elavon / Nova Virtual Merchant Gateway requires curl with SSL support'));
     }
 
     //Create the array of variables to be sent to the processor from the $params array
diff --git a/CRM/Core/Payment/FirstData.php b/CRM/Core/Payment/FirstData.php
index a8f5b4f7ff42d2239ce9865195ba2e250dbd93e7..860a4f6c87b252f2f29bd98757f075429eb154ef 100644
--- a/CRM/Core/Payment/FirstData.php
+++ b/CRM/Core/Payment/FirstData.php
@@ -156,11 +156,11 @@ class CRM_Core_Payment_FirstData extends CRM_Core_Payment {
    */
   public function doDirectPayment(&$params) {
     if ($params['is_recur'] == TRUE) {
-      CRM_Core_Error::fatal(ts('First Data - recurring payments not implemented'));
+      throw new CRM_Core_Exception(ts('First Data - recurring payments not implemented'));
     }
 
     if (!defined('CURLOPT_SSLCERT')) {
-      CRM_Core_Error::fatal(ts('%1 - Gateway requires curl with SSL support', [1 => $paymentProcessor]));
+      throw new CRM_Core_Exception(ts('%1 - Gateway requires curl with SSL support', [1 => $paymentProcessor]));
     }
 
     /**********************************************************
diff --git a/CRM/Core/Payment/PayPalImpl.php b/CRM/Core/Payment/PayPalImpl.php
index 42fdfa2f8052d8588edaedeaddde121995fc3f12..092ef82ec028cf7ec7c34faf9de3c6f0a8ad3035 100644
--- a/CRM/Core/Payment/PayPalImpl.php
+++ b/CRM/Core/Payment/PayPalImpl.php
@@ -929,7 +929,7 @@ class CRM_Core_Payment_PayPalImpl extends CRM_Core_Payment {
     // if recurring donations, add a few more items
     if (!empty($params['is_recur'])) {
       if (!$params['contributionRecurID']) {
-        CRM_Core_Error::fatal(ts('Recurring contribution, but no database id'));
+        throw new CRM_Core_Exception(ts('Recurring contribution, but no database id'));
       }
 
       $paypalParams += [
diff --git a/CRM/Core/Payment/PayflowPro.php b/CRM/Core/Payment/PayflowPro.php
index 1d4b92c5e96ce64fb9fad1c3c35985c721dcc6b7..662f6f9640a6c4cf4dd53138ab4219d96699b312 100644
--- a/CRM/Core/Payment/PayflowPro.php
+++ b/CRM/Core/Payment/PayflowPro.php
@@ -58,7 +58,7 @@ class CRM_Core_Payment_PayflowPro extends CRM_Core_Payment {
    */
   public function doDirectPayment(&$params) {
     if (!defined('CURLOPT_SSLCERT')) {
-      CRM_Core_Error::fatal(ts('Payflow Pro requires curl with SSL support'));
+      throw new CRM_Core_Exception(ts('Payflow Pro requires curl with SSL support'));
     }
 
     /*
@@ -373,7 +373,7 @@ class CRM_Core_Payment_PayflowPro extends CRM_Core_Payment {
    * @throws Exception
    */
   public function doTransferCheckout(&$params, $component) {
-    CRM_Core_Error::fatal(ts('This function is not implemented'));
+    throw new CRM_Core_Exception(ts('This function is not implemented'));
   }
 
   /**
diff --git a/CRM/Core/Payment/PaymentExpress.php b/CRM/Core/Payment/PaymentExpress.php
index 2f40ea054f080877e1e85a12e1339eab56f9f179..643119444f20bc32e033f614f48fbf7e42f16d04 100644
--- a/CRM/Core/Payment/PaymentExpress.php
+++ b/CRM/Core/Payment/PaymentExpress.php
@@ -103,7 +103,7 @@ class CRM_Core_Payment_PaymentExpress extends CRM_Core_Payment {
    *   Assoc array of input parameters for this transaction.
    */
   public function doDirectPayment(&$params) {
-    CRM_Core_Error::fatal(ts('This function is not implemented'));
+    throw new CRM_Core_Exception(ts('This function is not implemented'));
   }
 
   /**
@@ -118,7 +118,7 @@ class CRM_Core_Payment_PaymentExpress extends CRM_Core_Payment {
     $component = strtolower($component);
     $config = CRM_Core_Config::singleton();
     if ($component != 'contribute' && $component != 'event') {
-      CRM_Core_Error::fatal(ts('Component is invalid'));
+      throw new CRM_Core_Exception(ts('Component is invalid'));
     }
 
     $url = CRM_Utils_System::externUrl('extern/pxIPN');
@@ -211,7 +211,7 @@ class CRM_Core_Payment_PaymentExpress extends CRM_Core_Payment {
       }
       else {
         // calling DPS failed
-        CRM_Core_Error::fatal(ts('Unable to establish connection to the payment gateway.'));
+        throw new CRM_Core_Exception(ts('Unable to establish connection to the payment gateway.'));
       }
     }
     else {
diff --git a/CRM/Core/Payment/PaymentExpressIPN.php b/CRM/Core/Payment/PaymentExpressIPN.php
index 1bac6b1f9b5bbde1485a172163f0738742aa7ed9..3fc3ed9528a1b25af882920dc9c4a04a04ccb747 100644
--- a/CRM/Core/Payment/PaymentExpressIPN.php
+++ b/CRM/Core/Payment/PaymentExpressIPN.php
@@ -308,7 +308,7 @@ class CRM_Core_Payment_PaymentExpressIPN extends CRM_Core_Payment_BaseIPN {
         $info = curl_getinfo($curl);
         if ($info['http_code'] < 200 || $info['http_code'] > 299) {
           $log_message = "DPS error: HTTP {$info['http_code']} retrieving {$info['url']}.";
-          CRM_Core_Error::fatal($log_message);
+          throw new CRM_Core_Exception($log_message);
         }
         else {
           fwrite($message_log, sprintf("\n\r%s:- %s\n", date("D M j G:i:s T Y"), $response));
@@ -318,7 +318,7 @@ class CRM_Core_Payment_PaymentExpressIPN extends CRM_Core_Payment_BaseIPN {
           $valid = CRM_Core_Payment_PaymentExpressUtils::_xmlAttribute($response, 'valid');
           // CRM_Core_Payment_PaymentExpressUtils::_xmlAttribute() returns NULL if preg fails.
           if (is_null($valid)) {
-            CRM_Core_Error::fatal(ts("DPS error: Unable to parse XML response from DPS.", [1 => $valid]));
+            throw new CRM_Core_Exception(ts("DPS error: Unable to parse XML response from DPS.", [1 => $valid]));
           }
           $success = CRM_Core_Payment_PaymentExpressUtils::_xmlElement($response, 'Success');
           $txnId = CRM_Core_Payment_PaymentExpressUtils::_xmlElement($response, 'TxnId');
@@ -334,7 +334,7 @@ class CRM_Core_Payment_PaymentExpressIPN extends CRM_Core_Payment_BaseIPN {
       }
       else {
         // calling DPS failed
-        CRM_Core_Error::fatal(ts('Unable to establish connection to the payment gateway to verify transaction response.'));
+        throw new CRM_Core_Exception(ts('Unable to establish connection to the payment gateway to verify transaction response.'));
         exit;
       }
     }
diff --git a/CRM/Core/Payment/ProcessorForm.php b/CRM/Core/Payment/ProcessorForm.php
index 322f07cfd2f3ba908cc1f8311240d1bde485de47..3f927557b0bd819fb2d4570d931dfd7f1bd21710 100644
--- a/CRM/Core/Payment/ProcessorForm.php
+++ b/CRM/Core/Payment/ProcessorForm.php
@@ -106,7 +106,7 @@ class CRM_Core_Payment_ProcessorForm {
     if (!empty($form->_values['is_monetary']) &&
       !$form->_paymentProcessor['class_name'] && empty($form->_values['is_pay_later'])
     ) {
-      CRM_Core_Error::fatal(ts('Payment processor is not set for this page'));
+      CRM_Core_Error::statusBounce(ts('Payment processor is not set for this page'));
     }
 
     if (!empty($form->_membershipBlock) && !empty($form->_membershipBlock['is_separate_payment']) &&
@@ -115,7 +115,7 @@ class CRM_Core_Payment_ProcessorForm {
       )
     ) {
 
-      CRM_Core_Error::fatal(ts('This contribution page is configured to support separate contribution and membership payments. This %1 plugin does not currently support multiple simultaneous payments, or the option to "Execute real-time monetary transactions" is disabled. Please contact the site administrator and notify them of this error',
+      CRM_Core_Error::statusBounce(ts('This contribution page is configured to support separate contribution and membership payments. This %1 plugin does not currently support multiple simultaneous payments, or the option to "Execute real-time monetary transactions" is disabled. Please contact the site administrator and notify them of this error',
           [1 => $form->_paymentProcessor['payment_processor_type']]
         )
       );
diff --git a/CRM/Core/Payment/eWAY.php b/CRM/Core/Payment/eWAY.php
index 8f198b46c82483316aab9c4c28be5fcbbd42e14c..ba52b0f8a09ed6cca6e6b8e4a07ed5b86a6b3b8c 100644
--- a/CRM/Core/Payment/eWAY.php
+++ b/CRM/Core/Payment/eWAY.php
@@ -139,11 +139,11 @@ class CRM_Core_Payment_eWAY extends CRM_Core_Payment {
    */
   public function doDirectPayment(&$params) {
     if (CRM_Utils_Array::value('is_recur', $params) == TRUE) {
-      CRM_Core_Error::fatal(ts('eWAY - recurring payments not implemented'));
+      throw new CRM_Core_Exception(ts('eWAY - recurring payments not implemented'));
     }
 
     if (!defined('CURLOPT_SSLCERT')) {
-      CRM_Core_Error::fatal(ts('eWAY - Gateway requires curl with SSL support'));
+      throw new CRM_Core_Exception(ts('eWAY - Gateway requires curl with SSL support'));
     }
 
     // eWAY Client ID