+ Start a Discussion
IC-TannerIC-Tanner 

Calling ConvertLead() method on "after update" trigger

The method works via a "after insert" trigger but I receive the following error trying to "after update": 

 

Apex trigger autoLeadConvertTrigger caused an unexpected exception, contact your administrator: autoLeadConvertTrigger: execution of AfterUpdate caused by: System.DmlException: ConvertLead failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, autoLeadConvertTrigger: execution of AfterUpdate caused by: System.DmlException: ConvertLead failed. First exception on row 0; first error: CANNOT_UPDATE_CONVERTED_LEAD, cannot reference converted lead Class.autoLeadConvert.ConvertLead: line 100, column 3 Trigger.autoLeadConvertTrigger: line 14, column 7: Class.autoLeadConvert.ConvertLead: line 100, column 3

 

The main note of importance is the "CANNOT_UPDATE_CONVERTED_LEAD" error. The reason I'm doing an after update instead of after insert is to be able to have the workflow / auto-response rules run before conversion. (workflow / auto-response rules execute after triggers). 

 

What I don't understand is why this is not working for the "after update" trigger. The error appears to be coming from the leadConvert method trying to update the convert lead record fields such as: setContactId, etc.  This doesn't seem to make sense though as to why it would work in the 'after insert' trigger. 

 

Here is the basics of my code:

 

public static void ConvertLead(lead[] leads){

 

for (lead l : leads){

 

account Account = new account();

contact Contact = new contact();

 

//convert lead

converter.setLeadId(l.id);

converter.setContactId(contact.id);

converter.setAccountId(account.id);

converter.setOwnerId(l.OwnerId);

LeadStatus convertStatus = [Select Id, MasterLabel from LeadStatus where IsConverted=true limit 1]; converter.setConvertedStatus(convertStatus.MasterLabel);

converter.setDoNotCreateOpportunity(true);

Database.ConvertLead(converter);

 

The apex documentation states the following in regards to considerations for trigger context variables:

 

Can update original object using an update DML operation: 

 

Trigger Event: After Insert 

"Allowed"  

 

Trigger Event: After Update

"Allowed. Even though a bad script could cause an infinite recursion doing this incorrectly, the error would be found by the governor limits." 

 

I know I'm not running governor limits so I'm a missing something or is this a SF bug?

 

Thanks ahead of time! 

 

 

Message Edited by IC-Tanner on 02-25-2009 12:33 PM
Best Answer chosen by Admin (Salesforce Developers) 
jkucerajkucera

Sorry for the delayed response on this - I just discovered this thread.

 

Here's the problem - the trigger that calls the method to converts the lead gets called twice, as the act of converting a lead is an update that triggers all the save order stuff again. The 2nd time around, it tries to convert the already converted lead, throwing an exception & rolling back the whole transaction.

 

To resolve the issue, nest the method call inside an if statement that checks if the lead has been converted:

 

trigger convertleads on Lead (after update){ List<Lead> nonConvertedLeads=new List<lead>(); for (lead l: trigger.new){ if (l.isconverted==false){ nonConvertedLeads.add(l); } } convertLead(nonConvertedLeads); }

 


 

All Answers

WhyserWhyser
Where are you getting the Ids from Account and Contact? I see you instantiated those variables, but I don't see how there can be any ID set for them if no data was queried.
AttackAttack

Hello folks,

Incidentally I am facing the same issue today that  IC-Tanner is facing. I even dont update the account or contact by retrieveing their ids ... still the error is coming

 

Apex trigger leadCovert caused an unexpected exception, contact your administrator: leadCovert: execution of AfterUpdate caused by: System.DmlException: ConvertLead failed. First exception on row 0; first error: UNKNOWN_EXCEPTION, System.DmlException: Update failed. First exception on row 0 with id 00Q8000000NrIKbEAN; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, leadCovert: execution of AfterUpdate caused by: System.DmlException: ConvertLead failed. First exception on row 0; first error: CANNOT_UPDATE_CONVERTED_LEAD, cannot reference converted lead Class.convertLead.ConvertLead: line 18, column 7 Trigger.leadCovert: line 8, column 13 (System Code) : Class.convertLead.ConvertLead: line 18, column 7

 

 

Any advise folks ?

WhyserWhyser

I wonder if this has anything to do with the insert statements failing for all test methods going on today.
See: http://community.salesforce.com/sforce/board/message?board.id=apex&thread.id=12969

 

Does your account object have any auto text or auto number fields?

IC-TannerIC-Tanner

Hi Whyser, I left out query code in which I check for dupes and obtain the ids. The "setContactId" and "setAccountId" still process even if there is no previous ids passed. (in the case where no dupes are found and new contact and account records are created). The code developed works perfectly fine via a 'after insert' trigger but causes the error on a 'after update'.  What is confusing is that the APEX documentation states:

 

Trigger Event: After Update

"Allowed. Even though a bad script could cause an infinite recursion doing this incorrectly, the error would be found by the governor limits." 

 

So it seems to me this should work as I'm not reaching any governor limits.. Stuck before that could occur with the error noted in my initial post.

 

Note:

The reason why I want to do an 'after update' trigger is because the 'auto-response' rules and 'workflow' rules are not executing because they come after triggers in the execution order. And it appears the special behavior of lead records (not deleting after convert but simply becoming inacessible in the SF UI because the field: "isconverted = 1) will not fire the  'auto-response' rules and 'workflow' rules after a lead is converted. (even though the record still exists and logically appears that it should fire the rules). 

IC-TannerIC-Tanner

Is your error occuring on an 'after update' trigger? Even if you aren't using the setContactId() or setAccountId(), the lead record is still updating the lead record after conversion with values in the fields: ConvertedAccountId, ConvertedContactId, etc. 

 


Attack wrote:

Hello folks,

Incidentally I am facing the same issue today that  IC-Tanner is facing. I even dont update the account or contact by retrieveing their ids ... still the error is coming

 

Apex trigger leadCovert caused an unexpected exception, contact youradministrator: leadCovert: execution of AfterUpdatecaused by: System.DmlException: ConvertLead failed. First exception onrow 0; first error: UNKNOWN_EXCEPTION, System.DmlException: Updatefailed. First exception on row 0 with id 00Q8000000NrIKbEAN; firsterror: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, leadCovert: execution ofAfterUpdatecaused by: System.DmlException: ConvertLead failed. First exception onrow 0; first error: CANNOT_UPDATE_CONVERTED_LEAD, cannot referenceconverted leadClass.convertLead.ConvertLead: line 18, column 7Trigger.leadCovert: line 8, column 13(System Code): Class.convertLead.ConvertLead: line 18, column 7

 

 

Any advise folks ?


 

 

AttackAttack

Hi,

Yes, I am facing this issue in 'after update' event only .. it works fine for me in 'after insert'.

 

And yes I understand that the contact and account will be set automatically but I just mentioned this to clear the doubt for Whyser

WhyserWhyser

Does it even matter if you make your trigger fire before or after update?

In terms of the order of execution, your assignment rules, auto-response rules, and workflow rules run AFTER your after trigger code executes.

If that's the case, then if there are any workflow rules that do a field update on the lead, it should fail, because by then your lead should have already been converted.

 

If somehow the field upate (on leads I'm assuming) workflow rule was able to run successfully, it would then trigger your before and after triggers again, which should then cause an error since you may be trying to convert an already converted lead.

 

Basically what I'm saying is that workflow rules field updates can re-run your triggers. I have had this happen before where my apex triggers were firing twice. Not sure if that's the case with you.

Message Edited by Whyser on 02-26-2009 01:17 PM
jkucerajkucera

Sorry for the delayed response on this - I just discovered this thread.

 

Here's the problem - the trigger that calls the method to converts the lead gets called twice, as the act of converting a lead is an update that triggers all the save order stuff again. The 2nd time around, it tries to convert the already converted lead, throwing an exception & rolling back the whole transaction.

 

To resolve the issue, nest the method call inside an if statement that checks if the lead has been converted:

 

trigger convertleads on Lead (after update){ List<Lead> nonConvertedLeads=new List<lead>(); for (lead l: trigger.new){ if (l.isconverted==false){ nonConvertedLeads.add(l); } } convertLead(nonConvertedLeads); }

 


 
This was selected as the best answer