1

I have a simple trigger where when an opportunity is inserted, it creates a child object. If the opportunity is updated, it deletes all child objects and creates a new one. However, I receive an error from trying to insert the child object after the opportunity update:

CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, Create_Targeting_Allocation: maximum trigger depth exceeded Opportunity trigger event AfterUpdate for [006e0000006R2yM] ...: []: Trigger.Create_Targeting_Allocation: line 37, column 1`

Could someone help me figure out how to insert child records on an update trigger? Code is here:

trigger Create_Targeting_Allocation on Opportunity (after insert, after update) {

    if (trigger.isinsert || trigger.isundelete) {

        list<targeting_allocation__c> childs = new list<targeting_allocation__c>();

        for (opportunity o: trigger.new) {
            targeting_allocation__c child = new targeting_allocation__c ();
            child.allocation_opportunity__c = o.id;
            child.Allocation_Percent__c = 100;
            child.Program_Type__c = o.program_type__c;

            childs.add(child);
        }

        insert Childs;
    }

    if (trigger.isupdate) {
        set<id> ids = new set<id>();
        list<targeting_allocation__c> toInsert = new list<targeting_allocation__c>();
        for(opportunity o: trigger.new) {
            if (o.id != null) {
                ids.add(o.id);
            }
        }
        delete [select id from targeting_allocation__c where allocation_opportunity__c in :ids];

        for(opportunity o: [select id, program_type__c from opportunity where id in :ids]) {
            targeting_allocation__c x = new targeting_allocation__c ();
            x.allocation_opportunity__c = o.id;
            x.Allocation_Percent__c = 100;
            x.Program_Type__c = o.program_type__c;

            toInsert.add(x);
        }
        insert toInsert;
    }

}
  • There's a hard cap on trigger depth, I believe it's 16. From what I've read, it's usually due to recursive trigger behavior. I'm on the road and didn't look at the code you posted, but I would make sure you don't have any scenarios where you have triggers recursively firing – Brian Mansfield Jul 15 '15 at 21:50
1

Your trigger is getting caught in an endless loop when it fires because it has to fire again after the DML operation that occurs when new records are created or existing records are deleted/updated. What you need to do in order to fix this is create a utility class which the trigger calls to declare a Public Static Boolean Variable as follows:

public with sharing class TriggerUtil{

   public static boolean reEntry = false;

}

This variable gets evaluated upon each entry into the trigger. You do that something like below:

trigger Create_Targeting_Allocation on Opportunity (after insert, after update) { 

   If(!TriggerUtil.ReEntry){

      TriggerUtil.ReEntry = True;

      // Run trigger logic

   } // end if

} // end 

The next time the trigger fires in the same execution context, the value of ReEntry will be 'True', so the trigger won't execute and that stops the recursion. Now, because you have both after Insert and AfterUpdate, you may need to be selective about where you locate your Test. OR, you may need to use two separate Tests/Classes so the trigger repeats in one context, but not in the other.

  • Thank you all for your responses! I didn't realize that creating a child with a master-detail relationship would proc an update on the parent. Could I also do a check to see if a field is == from old.map to new.map and only delete/insert at that point? This should stop the recursion if I'm understanding it correctly... – krewllobster Jul 16 '15 at 13:20
  • Yes, you can do tests to limit the records you want to update or delete. That is in fact, the appropriate method to use. Use an If condition to create a set of Ids to operate on from trigger.new. Compare with values from trigger.old for AfterUpdate context. in an AfterInsert trigger, values of trigger.old are irrelevant since there are no "old" values to compare with. – crmprogdev Jul 16 '15 at 13:30
  • Beautiful. I just added: if (o.program_type__c != trigger.oldmap.get(o.id).program_type__c) inside my update trigger for loop that generates the opportunities to operate on, and it works perfectly. Thanks for the confirmation! – krewllobster Jul 16 '15 at 13:34
0

If you do not have any triggers on the Targeting_Allocation__c object then I would have to assume that in some way your child records are causing opportunities to be updated. This could be because of workflow rules or fields leveraging a master detail relationship.

Since there is no constraining condition on when you destroy and recreate children which are related to the opportunity, runaway recursion is the most probable cause of the issue displayed here.

The solution is to either tackle your parent opportunity being updated on the deletion and recreation of its children, or a way to bound your recursion by using some sort of condition on when to actually delete and recreate children.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.