+ Start a Discussion
Evelyn FayadEvelyn Fayad 

Developer Script Exception Error

I have a trigger that is creating a ton of errors. 

Active Contact Trigger - This trigger counts the number of active contacts (contacts that have been touched by the account owner in the last 14 days) and displays the total number on the Account. 
  • ERRORS THAT I AM GETTING FROM THIS TRIGGER: 
    • ActiveContact: execution of AfterUpdate caused by: System.DmlException: Update failed.
    • ActiveContact: System.LimitException: ApexCPU time limit exceeded
Here is the trigger itself: 
trigger ActiveContact on Contact (after insert, after update) {
    Contact[] cons;
    if (Trigger.isDelete) 
        cons = Trigger.old;
    else
        cons = Trigger.new;
    // get list of accounts
    Set<ID> acctIds = new Set<ID>();
    for (Contact con : cons) {
            acctIds.add(con.AccountId);
    }
    Map<ID, Contact> contactsForAccounts = new Map<ID, Contact>([select Id
                                                            ,AccountId
                                                            from Contact
                                                            where AccountId in :acctIds
                                                            AND Active_Contacts__c = 1 ]);
    
    Map<ID, Account> acctsToUpdate = new Map<ID, Account>([select Id
                                                                 ,Number_of_Active_Contacts__c
                                                                  from Account
                                                                  where Id in :acctIds]);
                                                                 
    for (Account acct : acctsToUpdate.values()) {
        Set<ID> conIds = new Set<ID>();
        for (Contact con : contactsForAccounts.values()) {
            if (con.AccountId == acct.Id)
                conIds.add(con.Id);
        }
        if (acct.Number_of_Active_Contacts__c != conIds.size())
            acct.Number_of_Active_Contacts__c = conIds.size();
    }
    update acctsToUpdate.values();
}


Can anyone give insight into why I am getting these errors? 
 
Amit Chaudhary 8Amit Chaudhary 8
Please try below code
trigger ActiveContact on Contact (after insert, after update) 
{
    Contact[] cons;
	
    if (Trigger.isDelete) 
        cons = Trigger.old;
    else
        cons = Trigger.new;
		
    // get list of accounts
    Set<ID> acctIds = new Set<ID>();
    for (Contact con : cons) 
	{
            acctIds.add(con.AccountId);
    }
	
	if(acctIds.size() > 0 )
	{
		List<Account> lstAcc = [ select Id ,Number_of_Active_Contacts__c  
								 ( Select Id,AccountId from contacts where Active_Contacts__c = 1 ) 
								 from account where id in :acctIds
								] ;
		List<Account> lstAccountToUpdate = new List<Account>();						
		
		for (Account acct : lstAcc ) 
		{
			List<Contact> lstCont = acct.contacts;
			if (acct.Number_of_Active_Contacts__c != lstCont.size())
			{
				acct.Number_of_Active_Contacts__c = lstCont.size();
				lstAccountToUpdate.add(acct);
			}	
		}
		if(lstAccountToUpdate.size()  > 0 )
		{
			update lstAccountToUpdate
		}
	}	
}

Please let us know if this will help you
 
karthikeyan perumalkarthikeyan perumal
Hello, 

 i excuted this code in my org it work well. may be you are processing bulk records. so the CPU time will not enough to update all record. 

use limit in your SOQL Query.  "like limit 2000" 

There is no specific setting that will increase CPU time for bulk api.

What is happening is that when you schedule data load through bulk it put system under stress and it is not able to finish the given task in appropriate time and so throws error Apex CPU time limit exceeded.
To avoid CPU limit you need to optimize your code. Here are few tips:
1) Check the trigger execution and note the required time.
2) With the help of developer console you can figure out where cup time is spent and then target the area which most CUP costly.
3) try and optimize those costly code blocks
4) Note for optimization of trigger you can use anomalous block to fire trigger
here is link that show how to use developer console for code optimization

here is the tips to optimize your code. 

https://help.salesforce.com/articleView?id=000232681&language=en_US&type=1


Hope this helps you. 

Thanks
karthik
 
karthikeyan perumalkarthikeyan perumal
And here is some more tips to find out

This code doesn’t seem too inefficient at first pass but know that the limit you mention is a limit shared across ALL your triggers.
So you could have trigger 1 and trigger 2 on the same object. Trigger 1 could be using 99% of the limit, then trigger 2 would use the last 1% afterwards and you’ll get the error on trigger 2. In reality, trigger 1 is the culprit!
So take a look at all code in your org that’s also running at the same time and make sure those are optimized too!


Do the Following thing. 

NOTE: inactive all the trigger in your Contact and account for time being,.  And activate this trigger. now check the update to find out the reason . 

Thanks
karthik
 
Amit Chaudhary 8Amit Chaudhary 8
Hi Evelyn Fayad,

That issue was coming in your code because code was not bulkify.

Due to below code that "ApexCPU time limit exceeded" Error is coming.
 
for (Account acct : acctsToUpdate.values()) {
        Set<ID> conIds = new Set<ID>();
        for (Contact con : contactsForAccounts.values()) {
            if (con.AccountId == acct.Id)
                conIds.add(con.Id);
        }
        if (acct.Number_of_Active_Contacts__c != conIds.size())
            acct.Number_of_Active_Contacts__c = conIds.size();
    }
NOTE:- You are using For loop inside for loop. For Each Account You are looping all Contact

Please try below code
trigger ActiveContact on Contact (after insert, after update) 
{
    Contact[] cons;
	
    if (Trigger.isDelete) 
        cons = Trigger.old;
    else
        cons = Trigger.new;
		
    // get list of accounts
    Set<ID> acctIds = new Set<ID>();
    for (Contact con : cons) 
	{
            acctIds.add(con.AccountId);
    }
	
	if(acctIds.size() > 0 )
	{
		List<Account> lstAcc = [ select Id ,Number_of_Active_Contacts__c  
								 ( Select Id,AccountId from contacts where Active_Contacts__c = 1 ) 
								 from account where id in :acctIds
								] ;
		List<Account> lstAccountToUpdate = new List<Account>();						
		
		for (Account acct : lstAcc ) 
		{
			List<Contact> lstCont = acct.contacts;
			if (acct.Number_of_Active_Contacts__c != lstCont.size())
			{
				acct.Number_of_Active_Contacts__c = lstCont.size();
				lstAccountToUpdate.add(acct);
			}	
		}
		if(lstAccountToUpdate.size()  > 0 )
		{
			update lstAccountToUpdate
		}
	}	
}



For more information please check below post
1) https://help.salesforce.com/articleView?id=000232681&language=en_US&type=1

Please let us know if this will help you
 
new sivanew siva
Modify the below trigger as per your requirement and mark is as best answer if it helps

trigger No_of_ContactsofAccount on contact(after insert, after update, after delete, after undelete){
if(trigger.isafter){
     set<id>acctidset=new set<id>();
  if(trigger.isinsert || trigger.isundelete){
        for(Contact cont:trigger.new){
           if(cont.accountid!=null){
           acctidset.add(cont.accountid);
           }
        }
     }
//For updated contacts
  if(trigger.isupdate){
        for(Contact cont:trigger.new){
          If(cont.accountid!=trigger.oldmap.get(cont.id).accountid ){
           contact c=trigger.oldmap.get(cont.id);
           ID Ids=c.accountid;
           acctidset.add(Ids);
           acctidset.add(cont.accountid);
           }
         }
  }
//For Deleted contacts
  if(trigger.isdelete){
     for(Contact cont:trigger.old){
     acctidset.add(cont.accountid);
     }
 }
 
     Map<id,integer> acctidvalMap=new Map<id,integer>();
       for(AggregateResult aggrs:[select accountid,Count(id)cnt from Contact where Accountid in:acctidset AND Active_Contacts__c = 1 group by accountid]){
       acctidvalMap.put((id)aggrs.get('accountid'),(integer)aggrs.get('cnt'));
       }
     
     List<Account> acctlist=new List<Account>();
       for(Account ac:[select id,No_of_Contacts__C from Account where id in:acctidset]){
         if(acctidvalMap.containskey(ac.id)){
         ac.Number_of_Active_Contacts__c=acctidValMap.get(ac.id);
         }
         else {
         ac.Number_of_Active_Contacts__c=0;
         }
         acctlist.add(ac);
       }
     
     if(acctlist.size()>0)
     update acctlist;
}
}
Evelyn FayadEvelyn Fayad
Thanks everyone, I can see how these solutions could solve the ApexCPU time limit exceeded error, but what about the AfterUpdate error:

ActiveContact: execution of AfterUpdate caused by: System.DmlException: Update failed

??