function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Harjeet Singh 28Harjeet Singh 28 

Update failed.First exception on row 0 with id ,first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY,LeadTrigger: maximum trigger depth exceeded,Lead trigger event AfterUpdate

Hi All,

Recently I encoutered the issue of maximum trigger depth exceeded. The thing is functionality is working fine in sandboxes but somehow it is showing errors in PROD.
My functionality is to assign leads on round robin basis and during bulk upload it shows the errors

Below is my trigger
trigger LeadTrigger on Lead (before insert,before update,after insert,after update) {    
    if(Trigger.isAfter){
        if(trigger.isInsert || trigger.isUpdate){
        RoundRobinImplementationHelper.roundRobinImplementation(Trigger.NewMap.keySet());
  }
 }
}

Below is my Apex class which assigns leads to users in round robin basis
public class RoundRobinImplementationHelper {
    public static void roundRobinImplementation(Set<Id> leadSet){
        System.debug('roundRobinImplementation ');
      List<Lead> leadList = [Select Id, OwnerId, Lead_Number__c FROM Lead Where Id IN : leadSet];
        List<User> userList = new List<User>();
        Set<Id> queueIdSet = new Set<Id>();
        Set<Id> userIdSet = new Set<Id>();
        Integer index, leadNumber, teamSize;
        
        For(Lead leadIterate : leadList){
            If(String.valueOf(leadIterate.ownerId).startsWith('00G')){
                queueIdSet.add(leadIterate.ownerId);
            }
        }
        If(queueIdSet==null || queueIdSet.size()==0)return;
        System.debug('queueIdSet '+queueIdSet);
        For(GroupMember gm : [Select Id, UserOrGroupId FROM GROUPMEMBER WHERE GroupId IN : queueIdSet]){
            userIdSet.add(gm.UserOrGroupId);
        }
        userList = [Select Id, Name,  Profile.Name From User Where Id In : userIdSet AND ISACTIVE = true];
        If(userList==null || userList.size()==0)return;
        
        For(Lead leadIterate : leadList){
                if(leadIterate.Lead_Number__c!=null){
                    leadNumber = Integer.valueOf(leadIterate.Lead_Number__c);
                    teamSize = userList.size();
                    index = Math.MOD(leadNumber ,teamSize);//+1;
                    system.debug('index '+index);
                    leadIterate.OwnerId = userList[index].id;
                    system.debug('leadIterate.OwnerId '+ leadIterate.OwnerId);
            }
        }
    If(leadList!=null && leadList.size()>0){
            update leadList;
        }
    }
}

What else I need to do here?How can I remove this error?

Any help will be greatly appreciated

Many thanks in advance​​​​​​​
Best Answer chosen by Harjeet Singh 28
Ajay K DubediAjay K Dubedi
Hi Harjeet,
The error in your code is because "You are updaing the lead in your code logic and because of that trigger runs again and again which is recursive trigger"
You can avoid it by implementing following logic in your code.

Trigger:
 
trigger LeadTrigger on Lead (before insert,before update,after insert,after update) {    
    if(Trigger.isAfter){
        if(trigger.isInsert || trigger.isUpdate){
            if(LeadHandler.isFirstTime){
LeadHandler.isFirstTime = false;
        RoundRobinImplementationHelper.roundRobinImplementation(Trigger.NewMap.keySet());
        }
  }
 }
}


Apex Class:
 
public class RoundRobinImplementationHelper {
    public static void roundRobinImplementation(Set<Id> leadSet){
        System.debug('roundRobinImplementation ');
      List<Lead> leadList = [Select Id, OwnerId, Lead_Number__c FROM Lead Where Id IN : leadSet];
        List<User> userList = new List<User>();
        Set<Id> queueIdSet = new Set<Id>();
        Set<Id> userIdSet = new Set<Id>();
        Integer index, leadNumber, teamSize;
        
        For(Lead leadIterate : leadList){
            If(String.valueOf(leadIterate.ownerId).startsWith('00G')){
                queueIdSet.add(leadIterate.ownerId);
            }
        }
        If(queueIdSet==null || queueIdSet.size()==0)return;
        System.debug('queueIdSet '+queueIdSet);
        For(GroupMember gm : [Select Id, UserOrGroupId FROM GROUPMEMBER WHERE GroupId IN : queueIdSet]){
            userIdSet.add(gm.UserOrGroupId);
        }
        userList = [Select Id, Name,  Profile.Name From User Where Id In : userIdSet AND ISACTIVE = true];
        If(userList==null || userList.size()==0)return;
        
        For(Lead leadIterate : leadList){
                if(leadIterate.Lead_Number__c!=null){
                    leadNumber = Integer.valueOf(leadIterate.Lead_Number__c);
                    teamSize = userList.size();
                    index = Math.MOD(leadNumber ,teamSize);//+1;
                    system.debug('index '+index);
                    leadIterate.OwnerId = userList[index].id;
                    system.debug('leadIterate.OwnerId '+ leadIterate.OwnerId);
            }
        }
    If(leadList!=null && leadList.size()>0){
            update leadList;
        }
    }
}

Apex Class to avoid recursiveness
 
public class LeadHandler
{
     public static Boolean isFirstTime = true;
}

I hope you find the above solution helpful. If it does, please mark as Best Answer to help others too.

Thanks and Regards,
Ajay Dubedi
www.ajaydubedi.com

All Answers

Khan AnasKhan Anas (Salesforce Developers) 
Hi Harjeet,

Greetings to you!

It is because of recursion. Recursion occurs when the same code is executed again and again. It can lead to infinite loop and which can result to governor limit sometime. Sometimes it can also result in unexpected output or the error “maximum trigger depth exceeded”. So, we should write code in such a way that it does not result to recursion.

Create a static variable in a class as true. Make it false before or after a trigger has been executed. Variable will become false when trigger runs for the first time. If the variable is true only then trigger will fire and if the trigger will try to execute the second time then it will not fire.

Handler Class:
public Class CheckRecursive {
    
    private static boolean run = true;
    
    public static boolean runOnce() {
        if(run) {
            run=false;
            return true;
        }
        else {
            return run;
        }
    }
}

Trigger:
trigger LeadClone on Lead (after insert) {
    
    if(CheckRecursive.runOnce()) {
         // Logic 
    }
}

Please refer to the below links which might help you further.

https://www.biswajeetsamal.com/blog/avoid-recursive-trigger-calls-in-salesforce/

http://www.sfdcpoint.com/salesforce/avoid-recursive-trigger-salesforce/

https://sagarsindhiblog.wordpress.com/2017/07/30/apex-trigger-what-is-recursion-and-solutions-to-avoid-recursion-in-apex-trigger/

I hope it helps you.

Kindly let me know if it helps you and close your query by marking it as solved so that it can help others in the future. It will help to keep this community clean.

Thanks and Regards,
Khan Anas
Ajay K DubediAjay K Dubedi
Hi Harjeet,
The error in your code is because "You are updaing the lead in your code logic and because of that trigger runs again and again which is recursive trigger"
You can avoid it by implementing following logic in your code.

Trigger:
 
trigger LeadTrigger on Lead (before insert,before update,after insert,after update) {    
    if(Trigger.isAfter){
        if(trigger.isInsert || trigger.isUpdate){
            if(LeadHandler.isFirstTime){
LeadHandler.isFirstTime = false;
        RoundRobinImplementationHelper.roundRobinImplementation(Trigger.NewMap.keySet());
        }
  }
 }
}


Apex Class:
 
public class RoundRobinImplementationHelper {
    public static void roundRobinImplementation(Set<Id> leadSet){
        System.debug('roundRobinImplementation ');
      List<Lead> leadList = [Select Id, OwnerId, Lead_Number__c FROM Lead Where Id IN : leadSet];
        List<User> userList = new List<User>();
        Set<Id> queueIdSet = new Set<Id>();
        Set<Id> userIdSet = new Set<Id>();
        Integer index, leadNumber, teamSize;
        
        For(Lead leadIterate : leadList){
            If(String.valueOf(leadIterate.ownerId).startsWith('00G')){
                queueIdSet.add(leadIterate.ownerId);
            }
        }
        If(queueIdSet==null || queueIdSet.size()==0)return;
        System.debug('queueIdSet '+queueIdSet);
        For(GroupMember gm : [Select Id, UserOrGroupId FROM GROUPMEMBER WHERE GroupId IN : queueIdSet]){
            userIdSet.add(gm.UserOrGroupId);
        }
        userList = [Select Id, Name,  Profile.Name From User Where Id In : userIdSet AND ISACTIVE = true];
        If(userList==null || userList.size()==0)return;
        
        For(Lead leadIterate : leadList){
                if(leadIterate.Lead_Number__c!=null){
                    leadNumber = Integer.valueOf(leadIterate.Lead_Number__c);
                    teamSize = userList.size();
                    index = Math.MOD(leadNumber ,teamSize);//+1;
                    system.debug('index '+index);
                    leadIterate.OwnerId = userList[index].id;
                    system.debug('leadIterate.OwnerId '+ leadIterate.OwnerId);
            }
        }
    If(leadList!=null && leadList.size()>0){
            update leadList;
        }
    }
}

Apex Class to avoid recursiveness
 
public class LeadHandler
{
     public static Boolean isFirstTime = true;
}

I hope you find the above solution helpful. If it does, please mark as Best Answer to help others too.

Thanks and Regards,
Ajay Dubedi
www.ajaydubedi.com
This was selected as the best answer