+ Start a Discussion
Tina Chang 6Tina Chang 6 

How to Fix this Apex Trigger? "The flow tried to update these records: null. This error occurred: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY: AccountTrigger"

Hello, there!

We have these two processes on Accounts in Process Builder -- one that updates a custom field called "Territory" based on the Billing State Code or the Billing City and/or the Region fields. The other that updates a custom field called "Region" based on the Billing Country field. Both processes have recently been getting the same error notifications as follows:
 
"The flow tried to update these records: null. This error occurred: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY: AccountTrigger: System.LimitException: Apex CPU time limit exceeded. For details, see API Exceptions."

Looks like it is being caused via the Process Builder but I suspect the root cause is the Apex here. Can you please look into this and see if the code needs to be made more efficient or fixed? I've attached the complete Apex trigger code and its test class below for your reference.

Please let me know if you require any further information. Your help will be greatly appreciated!

(My apologies this is a lof of code...)

AccountTrigger
/*******************************************************************************
 * AccountTrigger
 * @Description: Master Trigger for Accounts, which fires on ALL events to
 *               control the order in which trigger actions occur.  Follows the
 *               super trigger best practice from Salesforce:
 * 
 * https://developer.salesforce.com/page/Trigger_Frameworks_and_Apex_Trigger_Best_Practices
 * 
 * @Date: 12/15/2015
 * @Author: Jason Flippen (Demand Chain Systems)
 * 
 * @Updates: N/A
 *******************************************************************************/
trigger AccountTrigger on Account (before insert, before update)
{
                                                 // Determine what action is 
                                                 // occurring and when, and
                                                 // pass the correct context
                                                 // variables to the Trigger
                                                 // Handler class where all the
                                                 // actions will take place
    if (Trigger.isBefore && Trigger.isInsert) 
    {
                                                 // Before Insert
        AccountTriggerHandler.beforeInsert(Trigger.new,
                                           Trigger.newMap);
    }
    else if (Trigger.isBefore && Trigger.isUpdate) 
    {
                                                 // Before Update
        AccountTriggerHandler.beforeUpdate(Trigger.new,
                                           Trigger.newMap,
                                           Trigger.old,
                                           Trigger.oldMap);
    }

    /* FOR FRAMEWORK SETUP ONLY. NO ACTIONS ARE TAKEN AT THIS TIME
    else if (Trigger.isBefore && Trigger.isDelete) 
    {
                                                 // Before Delete
        AccountTriggerHandler.beforeDelete(Trigger.new,
                                           Trigger.newMap,
                                           Trigger.old,
                                           Trigger.oldMap);
    }
    else if (Trigger.isAfter && Trigger.isInsert)
    {
                                                 // After Insert
        AccountTriggerHandler.afterInsert(Trigger.new,
                                          Trigger.newMap);
    }
    else if (Trigger.isAfter && Trigger.isUpdate) 
    {
                                                 // After Update
        AccountTriggerHandler.afterUpdate(Trigger.new,
                                          Trigger.newMap,
                                          Trigger.old,
                                          Trigger.oldMap);
    }    
    else if (Trigger.isAfter && Trigger.isDelete) 
    {
                                                 // After Delete
        AccountTriggerHandler.afterDelete(Trigger.new,
                                          Trigger.old);
    }
    else if (Trigger.isAfter && Trigger.isUnDelete) 
    {
                                                 // After UnDelete
        AccountTriggerHandler.afterUnDelete(Trigger.new,
                                            Trigger.old);
    }
    */
    
}

AccountTriggerHandler​
/*******************************************************************************
 * AccountTriggerHandler
 * @Description: Class for handling all Account Trigger functionality.
 * 
 * @Date: 12/15/2015
 * @Author: Jason Flippen (Demand Chain Systems)
 * 
 * @Updates: N/A
 *******************************************************************************/
public with sharing class AccountTriggerHandler
{
    /*******************************************************************************
     * beforeInsert
     * @Description: Method for handling all "BeforeInsert" functionality.
     * 
     * @Date: 12/15/2015
     * @Author: Jason Flippen (Demand Chain Systems)
     * 
     * @Updates: N/A
     *******************************************************************************/
    public static void beforeInsert(List<Account> a_newRecordList,
                                   Map<Id,Account> a_newRecordMap)
    {
        System.debug('*** START: AccountTriggerHandler.beforeInsert()');
        
                                                 // Iterate through the new Account
                                                 // records and grab their SIC Code
                                                 // (if applicable).
        Set<String> sicCodeSet = new Set<String>();
        for (Account a : a_newRecordList)
        {
            if (a.Sic != null && a.Sic != '')
            {
                sicCodeSet.add(a.Sic);
            }
        }
        
                                                 // Do we have a Set of SIC Codes?
        if (!sicCodeSet.isEmpty())
        {
                                                 // Re-Iterate through the new Account
                                                 // records and set their reference to
                                                 // a SIC_Code__c record (if applicable).
            Map<String,Id> sicCodeIdMap = getSICCodeMap(sicCodeSet);
            for (Account a : a_newRecordList)
            {
                if (sicCodeIdMap.containsKey(a.Sic))
                {
                    a.SIC_Code__c = sicCodeIdMap.get(a.Sic);
                }
            }
        }
        
        System.debug('*** END: AccountTriggerHandler.beforeInsert()');
        
    } // End Method: beforeInsert()
    
    /*******************************************************************************
     * beforeUpdate
     * @Description: Method for handling all "Before Update" functionality.
     * 
     * @Date: 12/15/2015
     * @Author: Jason Flippen (Demand Chain Systems)
     * 
     * @Updates: N/A
     *******************************************************************************/
    public static void beforeUpdate(List<Account> a_newRecordList,
                                   Map<Id,Account> a_newRecordMap,
                                   List<Account> a_oldRecordList,
                                   Map<Id,Account> a_oldRecordMap)
    {
        System.debug('*** START: AccountTriggerHandler.beforeUpdate()');
        
                                                 // Iterate through the updated Account
                                                 // records and grab their SIC Codes
                                                 // (if applicable).
        Set<String> sicCodeSet = new Set<String>();
        for (Account a : a_newRecordList)
        {
                                                 // Was the SIC Code changed?
            if (a.Sic != a_oldRecordMap.get(a.Id).Sic)
            {
                                                 // If the SIC Code was removed, clear
                                                 // the Lookup field.
                if (a.Sic == null || a.Sic == '')
                {
                    a.SIC_Code__c = null;
                }
                else
                {
                    sicCodeSet.add(a.Sic);
                }
            }
        }
        
                                                 // Do we have a Set of SIC Codes?
        if (!sicCodeSet.isEmpty())
        {
                                                 // Re-Iterate through the updated Account
                                                 // records and set their reference to
                                                 // a SIC_Code__c record (if applicable).
            Map<String,Id> sicCodeIdMap = getSICCodeMap(sicCodeSet);
            for (Account a : a_newRecordList)
            {
                if (sicCodeIdMap.containsKey(a.Sic))
                {
                    a.SIC_Code__c = sicCodeIdMap.get(a.Sic);
                }
            }
        }
        
        System.debug('*** END: AccountTriggerHandler.beforeUpdate()');
        
    } // End Method: beforeUpdate()
    
    /*******************************************************************************
     * getSICCodeMap
     * @Description: Method for returning a Map of SIC Code-to-SIC Code Id.
     * 
     * @Date: 12/15/2015
     * @Author: Jason Flippen (Demand Chain Systems)
     * 
     * @Paramaters: Set<String> a_sicCodeSet
     * @Return: Map<String,Id> returnMap
     * 
     * @Updates: N/A
     *******************************************************************************/
    private static Map<String, Id> getSICCodeMap(Set<String> a_sicCodeSet)
    {
        System.debug('*** START: AccountTriggerHandler.getSICCodeMap()');
        
        Map<String,Id> returnMap = new Map<String,Id>();
        
                                                 // Iterate through the SIC Code records
                                                 // associated with the SIC Codes on the
                                                 // Account records that have been
                                                 // modified. 
        for (SIC_Code__c sc : [SELECT Id,
                                      Name
                               FROM   SIC_Code__c
                               WHERE  Name IN :a_sicCodeSet])
        {
                                                 // This SIC Code is associated with an
                                                 // Account that has been updated, so
                                                 // add it to the Map being returned.
            returnMap.put(sc.Name, sc.Id);
        }
        System.debug('*** returnMap: ' + returnMap);
        
        System.debug('*** END: AccountTriggerHandler.getSICCodeMap()');
        
        return returnMap;
        
    } // End Method: getSICCodeMap()
    
}

AccountTriggerHandlerTest​
/*******************************************************************************
 * AccountTriggerHandlerTest
 * @Description: Test class for AccountTriggerHandler class.
 * 
 * @Date: 12/15/2015
 * @Author: Jason Flippen (Demand Chain Systems)
 * 
 * @Updates: N/A
 *******************************************************************************/
@isTest
public class AccountTriggerHandlerTest
{
    private static final String sicCode_Name = '01110000';
    private static final String sicCode_Description = 'WHEAT';

    /*******************************************************************************
     * TestDataSetup
     * @Description: Method to create test data to be used throughout the class.
     * 
     * @Date: 12/15/2015
     * @Author: Jason Flippen (Demand Chain Systems)
     * 
     * @Updates: N/A
     *******************************************************************************/
    @testSetup static void TestDataSetup()
    {
        System.debug('*** START: AccountTriggerHandlerTest.test_beforeInsert()');
        
        Id sysAdminProfileId = [SELECT Id FROM Profile WHERE Name = 'System Administrator'].Id;
        Id execTeamRoleId = [SELECT Id FROM UserRole WHERE DeveloperName = 'ExecutiveTeam'].Id;
        
                                                 // Create System Administrator User.
        User adminUser = new User();
        adminUser.LastName = 'dr' + Crypto.getRandomInteger();
        adminUser.Email = adminUser.LastName + '@drtest.com';
        adminUser.UserName = adminUser.Email;
        adminUser.Alias = String.valueOf(adminUser.LastName.SubString(0,8));
        adminUser.ProfileId = sysAdminProfileId;
        adminUser.UserRoleId = execTeamRoleId;
        adminUser.LocaleSidKey = 'en_US';
        adminUser.LanguageLocaleKey = 'en_US';
        adminUser.TimeZoneSidKey = 'America/Los_Angeles';
        adminUser.EmailEncodingKey = 'UTF-8';
        insert(adminUser);
        
        system.runAs(adminUser)
        {
            SIC_Code__c sicCode = new SIC_Code__c();
            sicCode.Name = sicCode_Name;
            sicCode.Description__c = sicCode_Description;
            insert(sicCode);
        }
    }

    /*******************************************************************************
     * test_beforeInsert
     * @Description: Method to test the "beforeInsert" method.
     * 
     * @Date: 12/15/2015
     * @Author: Jason Flippen (Demand Chain Systems)
     * 
     * @Updates: N/A
     *******************************************************************************/
    public static testMethod void test_beforeInsert()
    {
        System.debug('*** START: AccountTriggerHandlerTest.test_beforeInsert()');
        
        Id sysAdminProfileId = [SELECT Id FROM Profile WHERE Name = 'System Administrator'].Id;
        Id execTeamRoleId = [SELECT Id FROM UserRole WHERE DeveloperName = 'ExecutiveTeam'].Id;
        
                                                 // Create System Administrator User.
        User adminUser = new User();
        adminUser.LastName = 'dr' + Crypto.getRandomInteger();
        adminUser.Email = adminUser.LastName + '@drtest.com';
        adminUser.UserName = adminUser.Email;
        adminUser.Alias = String.valueOf(adminUser.LastName.SubString(0,8));
        adminUser.ProfileId = sysAdminProfileId;
        adminUser.UserRoleId = execTeamRoleId;
        adminUser.LocaleSidKey = 'en_US';
        adminUser.LanguageLocaleKey = 'en_US';
        adminUser.TimeZoneSidKey = 'America/Los_Angeles';
        adminUser.EmailEncodingKey = 'UTF-8';
        insert(adminUser);
        
        system.runAs(adminUser)
        {
            Test.startTest();
            
            Account newAccount = new Account();
            newAccount.Name = 'Test Account';
            newAccount.CurrencyIsoCode = 'USD';
            newAccount.Website = 'http://www.somewhere.com/';
            newAccount.Vertical_Market__c = 'Marketplace';
            newAccount.E_Commerce_Solution_US__c = 'Amazon';
            newAccount.AlexaRating__c = '0-10K';
            newAccount.Sic = sicCode_Name;
            insert(newAccount);
            
            Test.stopTest();

            List<Account> newAccountList = [SELECT Id, SICDescription__c FROM Account WHERE Id = :newAccount.Id AND SICDescription__c = :sicCode_Description];
            //System.assert(newAccountList.size() > 0, 'Account was NOT created with SIC Code reference');            
        }
        
        System.debug('*** END: AccountTriggerHandlerTest.test_beforeInsert()');
        
    } // End Method: test_afterInsert()
    
    /*******************************************************************************
     * test_beforeUpdate
     * @Description: Method to test the "beforeUpdate" method.
     * 
     * @Date: 12/15/2015
     * @Author: Jason Flippen (Demand Chain Systems)
     * 
     * @Updates: N/A
     *******************************************************************************/
    public static testMethod void test_beforeUpdate()
    {
        System.debug('*** START: AccountTriggerHandlerTest.test_beforeUpdate()');
        
        Id sysAdminProfileId = [SELECT Id FROM Profile WHERE Name = 'System Administrator'].Id;
        Id execTeamRoleId = [SELECT Id FROM UserRole WHERE DeveloperName = 'ExecutiveTeam'].Id;
        
                                                 // Create System Administrator User.
        User adminUser = new User();
        adminUser.LastName = 'dr' + Crypto.getRandomInteger();
        adminUser.Email = adminUser.LastName + '@drtest.com';
        adminUser.UserName = adminUser.Email;
        adminUser.Alias = String.valueOf(adminUser.LastName.SubString(0,8));
        adminUser.ProfileId = sysAdminProfileId;
        adminUser.UserRoleId = execTeamRoleId;
        adminUser.LocaleSidKey = 'en_US';
        adminUser.LanguageLocaleKey = 'en_US';
        adminUser.TimeZoneSidKey = 'America/Los_Angeles';
        adminUser.EmailEncodingKey = 'UTF-8';
        insert(adminUser);
        
        system.runAs(adminUser)
        {
            Test.startTest();

            Account newAccount = new Account();
            newAccount.Name = 'Test Account';
            newAccount.CurrencyIsoCode = 'USD';
            newAccount.Website = 'http://www.somewhere.com/';
            newAccount.Vertical_Market__c = 'Marketplace';
            newAccount.E_Commerce_Solution_US__c = 'Amazon';
            newAccount.AlexaRating__c = '0-10K';
            insert(newAccount);
            
            List<Account> newAccountList = [SELECT Id, SICDescription__c FROM Account WHERE Id = :newAccount.Id AND SICDescription__c = :sicCode_Description];
            System.assert(newAccountList.size() == 0, 'Account was created with SIC Code Reference');            

            newAccount.Sic = sicCode_Name;
            update(newAccount);
            
            List<Account> updatedAccountList = [SELECT Id, SICDescription__c FROM Account WHERE Id = :newAccount.Id AND SICDescription__c = :sicCode_Description];
            //System.assert(updatedAccountList.size() > 0, 'Account was NOT updated with SIC Code Reference');            

            Test.stopTest();
        }
        
        System.debug('*** END: AccountTriggerHandlerTest.test_beforeUpdate()');
        
    } // End Method: test_beforeUpdate()
    
}

 
Best Answer chosen by Tina Chang 6
ashishashish
Hi,

This error is arising because!! when  process builder is tryin to update the custom field but  before this  'before Update' trigger fires which  possibly tries to update record.So this process is looping again to fire process builder and this goes on !!!

The workaround here would be to stop the recursion through below code:

    
public Class checkRecursion{
    
    public static run=false;
    
    public static boolean hasAlreadyRun(){
        return run;
    }
    
    public Static void setAlredyRun(){
        run=true;
    }
}

stop the recursion in the trigger through this class lik this :
 
//Account Trigger Class
else if (Trigger.isBefore && Trigger.isUpdate)
    {
        If(!checkRecursion.hasAlreadyRun())//enter first time in trigger but fails second time
        // Before Update
        AccountTriggerHandler.beforeUpdate(Trigger.new,
                                           Trigger.newMap,
                                           Trigger.old,
                                           Trigger.oldMap);
    }

//Account handler Class
public static void beforeUpdate(List<Account> a_newRecordList,
                                   Map<Id,Account> a_newRecordMap,
                                   List<Account> a_oldRecordList,
                                   Map<Id,Account> a_oldRecordMap)
    {
        //at the end of your code stop the recursion
        checkRecursion.setAlredyRun();
    }

try this out and let us know if this helps you.

Thanks

 

All Answers

ashishashish
Hi,

This error is arising because!! when  process builder is tryin to update the custom field but  before this  'before Update' trigger fires which  possibly tries to update record.So this process is looping again to fire process builder and this goes on !!!

The workaround here would be to stop the recursion through below code:

    
public Class checkRecursion{
    
    public static run=false;
    
    public static boolean hasAlreadyRun(){
        return run;
    }
    
    public Static void setAlredyRun(){
        run=true;
    }
}

stop the recursion in the trigger through this class lik this :
 
//Account Trigger Class
else if (Trigger.isBefore && Trigger.isUpdate)
    {
        If(!checkRecursion.hasAlreadyRun())//enter first time in trigger but fails second time
        // Before Update
        AccountTriggerHandler.beforeUpdate(Trigger.new,
                                           Trigger.newMap,
                                           Trigger.old,
                                           Trigger.oldMap);
    }

//Account handler Class
public static void beforeUpdate(List<Account> a_newRecordList,
                                   Map<Id,Account> a_newRecordMap,
                                   List<Account> a_oldRecordList,
                                   Map<Id,Account> a_oldRecordMap)
    {
        //at the end of your code stop the recursion
        checkRecursion.setAlredyRun();
    }

try this out and let us know if this helps you.

Thanks

 
This was selected as the best answer
Tina Chang 6Tina Chang 6
Hi, ashish! Thank you so much for your reply! My apologies if I misread your reply. Should I create this checkRecursion class? If so, I did and got this error message. Any idea on what I did wrong?

User-added image
 
ashishashish
oops that bcoz we have not specifiied the data type of variable:
here it goes "Public static boolean run=false;"
Tina Chang 6Tina Chang 6
Hi, @ashish! Thank you! I was able to create this checkRecursion class and update the Account Trigger Class and the Account Handler Class.  I wanted to push the checkRecursion code from sandbox to production and wrote a test class but couldn't figure out how.  Is it possible that you could show me how to write a test class for it?  Thank you!

I came up with the following but they are just nonsense... (sorry I am only an admin not an developer... don't know how to write code...)
 
@isTest

public Class TestCheckRecursion {
    
    static testmethod void checkRecursion.hasAlreadyRun() {
        run = TRUE;
    }
        System.assert(checkRecursion.hasAlreadyRun()) {
    }         
}

 
ashishashish

ohk!! does this appraoch stoppoed the recursion?
 

Tina Chang 6Tina Chang 6
@Ashish! My sincere apologies for the late reply.  I have been travelling in the past few days and had been working internally to coordinate and simulate the mass updates for testing in the sandbox last week.  The tests were successful!  Your fix works like a charm!  Is it possible that you could show me how to write a test class for the CheckRecursion class?  Thank you so much!