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');
}
}
}
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().
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
000383729

We use three kinds of cookies on our websites: required, functional, and advertising. You can choose whether functional and advertising cookies apply. Click on the different cookie categories to find out more about each category and to change the default settings.
Privacy Statement
Required cookies are necessary for basic website functionality. Some examples include: session cookies needed to transmit the website, authentication cookies, and security cookies.
Functional cookies enhance functions, performance, and services on the website. Some examples include: cookies used to analyze site traffic, cookies used for market research, and cookies used to display advertising that is not directed to a particular individual.
Advertising cookies track activity across websites in order to understand a viewer’s interests, and direct them specific marketing. Some examples include: cookies used for remarketing, or interest-based advertising.