+ Start a Discussion

Trigger Error when Mass Upserting Records - INVALID_FIELD_FOR_INSERT_UPDATE

I have an account trigger that has always worked fine with no problems, but today when I was doing a mass insert / update of records, I kept getting an error message:


Apex script unhandled trigger exception by user/organization: 00570000001Frz1/00D700000009SRz


AutoCltGroup: execution of BeforeInsert


caused by: System.DmlException: Insert failed. First exception on row 0 with id a0F70000009GrlXEAS; first error: INVALID_FIELD_FOR_INSERT_UPDATE, cannot specify Id in an insert call: [Id]


Trigger.AutoCltGroup: line 47, column 1



What do I need to change in my trigger code to prevent this type of error:


trigger AutoCltGroup on Account (before insert, before update) {

list <Client_Groups__c> CGs = new list <Client_Groups__c> ();
list <Client_Groups__c> CG996 = new list <Client_Groups__c> ();
list <Client_Groups__c> CG997 = new list <Client_Groups__c> ();

list <Account> P996 = new list <Account> ();
list <Account> P997 = new list <Account> ();
list <Account> A300 = new list <Account> ();
list <Account> A343 = new list <Account> ();
list <Client_Groups__c> NewCG = new list <Client_Groups__c> ();
list <Recordtype> CltRT = new list <Recordtype> ();

List<Account> Agency = new List <Account> {};

CGs = [Select ID From Client_Groups__c Where Name='UNGROUPED' limit 1];
CG996 = [Select ID From Client_Groups__c Where Name='RPM996' limit 1];
CG997 = [Select ID From Client_Groups__c Where Name='RPM997' limit 1];

P996 = [Select ID From Account Where Natl_Identifier__c='343-996-0' limit 1];
P997 = [Select ID From Account Where Natl_Identifier__c='300-997-0' limit 1];
A300 = [Select ID From Account Where Natl_Identifier__c='343-0-0' limit 1];
A343 = [Select ID From Account Where Natl_Identifier__c='300-0-0' limit 1];
CltRT = [Select ID From Recordtype Where Name='Client' limit 1];

for (Account a : trigger.new)
    if (a.cmr_number__c == '996' && CG996.size()>0)
        a.Client_Group__c = CG996[0].id;
        a.ParentId = P996[0].id;
        a.Agency_Account__c = A343[0].id;
    else if (a.cmr_number__c == '997' && CG997.size()>0)
        a.Client_Group__c = CG997[0].id;
        a.ParentId = P997[0].id;
        a.Agency_Account__c = A300[0].id;  

    else if (a.cmr_number__c != '997' && a.cmr_number__c != '996' && a.RecordTypeId == CltRT[0].id && a.Client_Group__c == null)
        (new Client_Groups__c
        (Name=a.client_name__c,Agency_Account__c = a.agency_account__r.id));
        insert NewCG;
        a.Client_Group__c = NewCG[0].id;  

    else if (a.cmr_number__c != '997' && a.cmr_number__c != '996' && a.Client_Group__c!= null)
        a.Client_Group__c = CGs[0].id;  


The insert newCG line should be outside the for loop.  In general you should avoid placing DML statements in for loops because you may exceed governor limits.


In this case, since you are adding to newCG and then inserting one record at a time -- when you add the first record and insert, it is given an ID, then when you add the second record and insert, the first record in the list already has an ID, hence the error.


Normally I would have put the insert piece outside the loop, but for this activity, once the new CG record is inserted, I then need to update the account record with that new CG id before moving on to the next one.


How would I do that if the insert is outside the loop?




A quick and dirty fix is to use a variable instead of a list.

Client_Groups__c newCG = new Client_Groups__c(blah blah blah);
insert newCG;
a.field__c = newCG.Id;


Jerun JoseJerun Jose

The cleaner fix would involve using collections .. mostly maps..


After the insert, iterate through the list and store the ids in a map of a key of your choice(usually a unique field available at both Client_Groups__c and Account objects).


Next would be to iterate through the account list agai, but this time use the map contents to populate the Client_Group__c field