Loading

Transaction control in Apex Class and Trigger with Exception Handling

Veröffentlichungsdatum: Jun 8, 2026
Beschreibung

In Salesforce Apex, if a DML operation initiated by an Apex class (which has a try/catch block) causes a trigger to execute, and the trigger encounters an unhandled exception, the exception propagates up the call stack. As a result, the catch block in the calling Apex class is bypassed — the exception is not caught by the class.


This is expected Salesforce platform behavior. The Apex runtime does not allow exceptions thrown inside a trigger context to be silently caught by an outer class-level catch block without additional transaction control logic.

 

Below are the sample trigger and Apex class which explains the behavior:

trigger TheTrigger on Account (before insert, after insert)
{
    System.debug('-- Creating an exception -- '+(2/0));
}

Apex Class

public class DemoClass 
{
    public void demoMethod()
    {
        Try
        {
            System.debug('--Entered--');
            Account acc = new Account(Name='Test');
            insert acc;
            System.debug('-account created --'+acc.Id);
            Contact con = new Contact(LastName='TestCon');
            insert con;
            System.debug('--Contact created'+con.Id);
        }
        catch(Exception exe)
        {
            System.debug('created new error log');
        }
    }
}
Lösung

Using Savepoint and Database.rollback to Control Transaction Flow

To prevent DML statements from committing to the database when a trigger encounters an error, use a combination of a static control variable, Database.setSavepoint(), and Database.rollback().

 

Implementation Steps

Step 1: Create a helper class with a static boolean variable to track execution state. Initialize the variable to true. When a trigger catches an exception, set this variable to false in its catch block.


Step 2: In the Apex class, before each significant DML operation, call Database.setSavepoint() to mark a restore point. Store the returned Savepoint object in a variable.

Step 3: After the DML operation, check the value of the static variable. If it is false (meaning the trigger encountered an error), call Database.rollback(sp) using the saved Savepoint. This undoes all DML performed since the savepoint was set.


Step 4: Repeat Steps 2–3 for each DML operation in the transaction that requires rollback capability.
This pattern ensures that if any trigger in the transaction fails, all related DML operations can be rolled back cleanly without relying on uncaught exception propagation.


Trigger

trigger TheTrigger on Account (before insert, after insert)
{
    try
    {
     System.debug('-- Throw an exception -- '+(2/0));   
    }
    catch(Exception exe)
    {
       DemoClass.stopTheExecution=false;
    }     
}

Apex Class

public class DemoClass 
{
    Public Static Boolean stopTheExecution=true;
    public void demoMethod()
    {
        Try
        {   
            Savepoint sp = Database.setSavepoint();         
            Account acc = new Account(Name='Test');
            insert acc;
            if(stopTheExecution==false)
            Database.rollback(sp);
            Savepoint sp2 = Database.setSavepoint();  
            System.debug('--account created ?-- '+acc.Id);
            Contact con = new Contact(LastName='TestCon');
            insert con;
            System.debug('--Contact created '+con.Id+ ' ====Static 
            variable== '+stopTheExecution);
            if(stopTheExecution==false)
            Database.rollback(sp2);           
        }
        catch(Exception exe)
        {
            System.debug('Handle Exception or create error log');
        }
    }
}


Please check Transaction Control for rules of using SavePoint and Rollback methods

Nummer des Knowledge-Artikels

000383729

 
Laden
Salesforce Help | Article