+ Start a Discussion

C# Salesforce API LeadConvertResult returning RECORD_IN_USE_BY_WORKFLOW

C# Salesforce API LeadConvertResult returning RECORD_IN_USE_BY_WORKFLOW.




I have searched all over the internet and the Developer Discussion boards and found nothing on this subject for the Salesforce API. Hopefully I am not alone.


At a high level, all I am trying to accomplish is converting a recently created Lead and convert that Lead into an Account and Contact.


When I call LeadConvert with a valid Lead I want to convert; the LeadConvertResult() is always returned statusCode = RECORD_IN_USE_BY_WORKFLOW



public string ConvertLeadToContactForAccount(string accountId, Lead lead)
LeadConvert convert = new LeadConvert
accountId = accountId,
leadId = lead.Id,
overwriteLeadSource = false,
doNotCreateOpportunity = true,
sendNotificationEmail = false,
convertedStatus = "Qualified"

LeadConvertResult[] results = SforceProvider.Instance.ConvertLead(convert);

// one save result with status success returns true
if (results.Length == 1 && results[0].success)
return results[0].contactId;

return string.Empty;


The only item that is really jumping out at me is some form of custom workflow behind the scenes that I am missing? I am using the salesforcedotnet library, with some customization, the Enterpise WSDL, and the profile connecting to the API has full admin access to everything in Salesforce.


Always ThinkinAlways Thinkin

You are not alone! Unfortunately, I don't have the answer!


I'm getting the same behavior although I know it is because of a Time-Based Workflow Trigger I am running. I need to delay the conversion of a Lead-to-PersonAccount long enough to allow DupeBlocker to check for duplicates and merge them. I attempted to do so by creating a 0-hour field update that would then fire an after-update Apex Trigger.


If I don't use the Time-Based Workflow action, the LeadConvert works fine (although DupeBlocker is skipped).Using the Time-Based Workflow I get the error.


What I find odd is that the field update doesn't actually happen, it appears to be rolled back along with the Apex Trigger. On its own, the update works fine even with DupeBlocker merging. DupeBlocker is able to delete the record with a pending Workflow, the Workflow stays in the queue for the resulting master record and eventually fires.


I suspect that the Apex Trigger is firing before the record of the Time-Based action is deleted. 


Please share any information you learned while investigating this error.


@Always Thinkin


Glad to hear I am not alone on this issue with LeadConvert() and Time-Based Workflow.


I too disabled the Time-Based Workflow action, and the LeadComvert() works as expected; unfortunately given the organizations requirements that Time-Based Workflow has to stay enabled.


Fortunately I did find more of a workaround that has been in place in production for about 3 weeks at this point, with little to no issues.


Here is the workaround (less a solution IMHO, still doesn't sit well with me).


Basically what we are doing is manually creating the Account, then creating the Contact to associate with that Account; based on the existing Lead data. At the end of the day, it is just a manual LeadConvert().


Quick breakdown:


1) Contact Exists, Lookup the Account, do our business logic (Opportunity, etc).

2) Contact does NOT exist, a Lead does exist, manually create a new Account based on the Lead data, manually create a Contact based on that Account and Lead data, do our business logic (Opportunity, etc).


There really was one caveat (that ConvertLead() handles), in that you have to update and save the Lead status as "In Process" before manually creating the Account or Contact. Works great from there.



updateLead.Status = "In Process";

string confirmLeadStatusResult = this._leadController.Update(updateLead);




Keep in mind we had to create some Apex Triggers, and some custom tools (simple really), because what happens is that Lead will still exist, so you get this scenario where you have a Lead/Account/Contact when in reality ConvertLead() does some 'magic' where the Lead is no longer available (I think LeadConverted is set to true), so you will only see Account/Contact (which is what you expect).


I had some input here and there from this, and at the end of the day the Time-based Workflows are a necessary evil, for a myriad of reasons beyond my control.



Always ThinkinAlways Thinkin

I found a way to circumvent the error but I'm not sure whether it's 100% reliable: I used an async @future method that is called when the time-based workflow field update is triggered.


I've tested it through the GUI and through an API insert but since we don't know exactly why the error happens in the first place, I cannot say whether the timing of the time-based workflow and the async call will always work out to allow the operation to succeed.


Interesting approach tothe issue.


I know the Time-Based Workflow for new Leads in our system, has two of them that are major. Unfortunately they run every 2 days, and one every 3. Basically calling AssignmentRules on Leads that have not been read, but still locking those Leads from the API for 3 days. After 3 days, LeadConvert() actually works, but waiting around for the Time-Based Workflow is not an option.


The GUI can Convert the Leads just fine, which is why it is so frustrating, and my approach leaves the Lead intact which is also annoying. I know it works, but it just seems like what I did is a 'dirty hack'.