Question
The “Maximum stack depth has been reached” error often occurs in Salesforce when there is an excessive chain of asynchronous operations, such as Queueable or Future calls, leading to a recursive or circular flow. This error is especially common when testing complex asynchronous logic with triggers and schedulable or queueable classes. Here, we’ll address a specific scenario and provide solutions.
A user has a setup where triggers handle lead suppression by enqueuing asynchronous jobs. Each trigger calls a Queueable
or Schedulable
class based on certain conditions, as shown in the provided example.
Trigger Example:
trigger HandleLeadSuppressionTrigger on Lead (after insert, after update) {
Set<Id> leadIds = new Set<Id>();
for (Lead lead : Trigger.new) {
if (Trigger.isInsert) {
if (lead.Related_Account__c != null || lead.Email != null || lead.Phone != null || lead.Related_Contact__c != null ||
(lead.PostalCode != null && lead.Company != null)) {
leadIds.add(lead.Id);
}
}
if (Trigger.isUpdate) {
Lead oldLead = Trigger.oldMap.get(lead.Id);
if ((lead.Related_Account__c != null && lead.Related_Account__c != oldLead.Related_Account__c) ||
(lead.Email != null && lead.Email != oldLead.Email) ||
(lead.Phone != null && lead.Phone != oldLead.Phone) ||
(lead.Related_Contact__c != null && lead.Related_Contact__c != oldLead.Related_Contact__c) ||
((lead.PostalCode != null && lead.PostalCode != oldLead.PostalCode) &&
(lead.Company != null && lead.Company != oldLead.Company))) {
leadIds.add(lead.Id);
}
}
}
if (!leadIds.isEmpty()) {
if (Limits.getLimitQueueableJobs() - Limits.getQueueableJobs() > 0) {
System.enqueueJob(new SuppressionQueue(null, null, null, leadIds));
} else {
String cronExp = Datetime.now().format('s m H d M ? yyyy');
System.schedule('Lead Suppression Job ' + Datetime.now(), cronExp, new SuppressionScheduler(null, null, null, leadIds));
}
}
}
Schedulable Class Example:
public class SuppressionScheduler implements Schedulable {
Set<Id> leadIds;
public SuppressionScheduler(Set<Id> leadIds) {
this.leadIds = leadIds;
}
public void execute(SchedulableContext sc) {
if (leadIds != null && !leadIds.isEmpty()) {
System.enqueueJob(new SuppressionQueue(null, null, null, leadIds));
}
}
}
This approach can inadvertently cause chained asynchronous operations, especially during testing, resulting in the stack depth error.
Answer
The user resolved the issue by refactoring the logic to eliminate unnecessary layers of asynchronous chaining. Specifically, the SuppressionQueue
class was removed, and the triggers and SuppressionScheduler
directly called the Queueable
classes performing DML operations.
Here is the refactored logic:
Trigger Example (Refactored):
trigger HandleLeadSuppressionTrigger on Lead (after insert, after update) {
Set<Id> leadIds = new Set<Id>();
for (Lead lead : Trigger.new) {
if (Trigger.isInsert) {
if (lead.Related_Account__c != null || lead.Email != null || lead.Phone != null || lead.Related_Contact__c != null ||
(lead.PostalCode != null && lead.Company != null)) {
leadIds.add(lead.Id);
}
}
if (Trigger.isUpdate) {
Lead oldLead = Trigger.oldMap.get(lead.Id);
if ((lead.Related_Account__c != null && lead.Related_Account__c != oldLead.Related_Account__c) ||
(lead.Email != null && lead.Email != oldLead.Email) ||
(lead.Phone != null && lead.Phone != oldLead.Phone) ||
(lead.Related_Contact__c != null && lead.Related_Contact__c != oldLead.Related_Contact__c) ||
((lead.PostalCode != null && lead.PostalCode != oldLead.PostalCode) &&
(lead.Company != null && lead.Company != oldLead.Company))) {
leadIds.add(lead.Id);
}
}
}
if (!leadIds.isEmpty()) {
System.enqueueJob(new SuppressionQueueable(leadIds));
}
}
Queueable Class:
public class SuppressionQueueable implements Queueable {
Set<Id> leadIds;
public SuppressionQueueable(Set<Id> leadIds) {
this.leadIds = leadIds;
}
public void execute(QueueableContext context) {
// Perform the DML operations for lead suppression
}
}
Key Takeaways
- Avoid chaining too many asynchronous calls in one flow. Each asynchronous operation consumes system resources and contributes to stack depth.
- Refactor unnecessary classes and simplify the flow wherever possible.
- Test thoroughly after changes to ensure the logic still meets business requirements.
With this refactoring, the “Maximum stack depth” error was resolved, and the test cases ran successfully.
Summing Up
The “Maximum stack depth has been reached” error in Salesforce occurs when excessive asynchronous calls, such as Queueable
or Schedulable
jobs, are chained, causing resource limits to be exceeded. In the provided example, the original trigger and scheduler logic used multiple asynchronous layers, leading to this error during testing.
The issue was resolved by refactoring the code to simplify the flow. The HandleLeadSuppressionTrigger
was modified to directly enqueue a Queueable
class (SuppressionQueueable
) instead of relying on intermediate layers like the SuppressionQueue
class. This approach reduced complexity, avoided excessive asynchronous chaining, and adhered to best practices.
Enroll for Salesforce Training Designed for Career Building Success
Our Salesforce Course is designed to provide you with a comprehensive understanding of the Salesforce platform, empowering you with the skills necessary for success in the CRM space. We cover essential modules such as Salesforce Admin, Developer, and AI, combining theoretical knowledge with hands-on learning.
Through real-time project work and practical assignments, you’ll be prepared to solve complex business problems using Salesforce solutions. Our experienced instructors ensure that you gain the practical skills and industry insights needed to thrive in the Salesforce ecosystem.
Along with in-depth technical training, our Salesforce training in Chennai offers personalized mentorship, certification guidance, and interview preparation to give you an edge in the competitive job market. You will receive detailed study materials, practical exposure through live projects, and one-on-one assistance throughout the course.
By the end of the training, you will not only be ready for certification exams but also equipped with the hands-on experience and problem-solving abilities that employers are seeking. Start your Salesforce journey with us and unlock the door to exciting career opportunities! Enroll for FREE demo!