I'm trying to debug a the following error:

UNABLE_TO_LOCK_ROW, unable to obtain exclusive access to this record: []

The error occurs when a method is called to create a task when an order fulfillment is submitted.

Here is the code:

private void createTasks() {
    List<Task> tasksToInsert = new List<Task>();
    for(Fulfillment_Recipient__c r : recipientList) {
        Task task = new Task();
        task.ActivityDate = Date.today();
        task.Status = 'Completed';
        task.Subject = 'Content Ordered';
        task.Type = 'Fulfillment Order';
        task.whoId = r.Contact__c;
        task.whatId = r.Order_Fulfillment__c;
    if(!tasksToInsert.isEmpty() && tasksToInsert.size() > 0) {
        insert tasksToInsert;

The error occurs on this line:

        insert tasksToInsert;

I've looked thru the logs and I can't see what is locking the record to stop the insert from happening.

Is there a way to capture additional log entries to see if there are any asynchronous/future logs spawned between the insertion of the task record? I'm wondering if there is an integration process that might be causing the lock or some other process?

I'm stumped on how to isolate the cause of this error.

Thanks for any suggestions.

  • n.b. the line if(!tasksToInsert.isEmpty() && tasksToInsert.size() > 0) is unnecessary, others have proven that if the list is empty, no DML attempt is even made so no governor limit is burned.
    – cropredy
    Nov 1, 2014 at 0:09

2 Answers 2


Is it consistently unable to lock the row? Or does the failure seem random? Are there any triggers running on inserting Task that could be locking something else? Are there any workflows running on the Task or Order Fulfilment? Is there a batch job running that could be looking at one of the relevant records? Is it calling out to an external system that is then calling back in to look at the records?

If you set the debug log to run for a given user, it debugs until that user's log requests run out. Each user has 20 requests. So if any future / async method is called, it'll create a debug log as long as one of the 20 remains. So you can set up debug logs for the user committing the order fulfilment and any integration user, and keep clicking "reset" on their debug log requests until you see something (or get bored of looking).


I think the best way of ensuring the DML operation is successful in a future call, is to use the ForUpdate when you select the Fulfillment_Recipient__c in order to link the task. You could see some examples here and here

If this doesn't work then you've got two more options, you either try to log the error or try to recover from the error (assuming that it`s stops everything)

I`ll just give you an example of a code that logs errors:

List<Database.Saveresult> dmlresults = Database.Update(ops, false);
List<Opportunity> FailedUpdates = new List<Opportunity>();
for(Integer x = 0; x < ops.size(); x++){
     Database.Saveresult sr - dmlresults[x];
           if(err.getStatusCode() == StatusCode.UNABLE_TO_LOCK_ROW){
     if(FailedUpdates.size() > 0){
           //Do a logging or recovery operation here

The Database.Update statement has a parameter opt_allOrNone which can be set to false to indicate that the code should return an error result rather than throwing an exception.

Logging DML lock errors with this scenario is straightforward - just use a custom object to store any failure information that you wish to track. While the opportunity record or in your case the Filfillment_Recipient__c record may be locjked, that won`t prevent you from inserting a new custom object.

Hope my answer will point you in the right direction and might not necessarily provide a fix for your problem or a definite answer

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .