1

When using the Salesforce API and creating an account using this endpoint POST https://<mycompany>.my.salesforce.com/services/data/v51.0/sobjects/Account/ we once in a while fails with a 400 with this stacktrace:

[{"message":"rh2.PS_Account: execution of AfterInsert

caused by: System.DmlException: Upsert failed. First exception on row 0 with id <ID_REMOVED>; first error: UNABLE_TO_LOCK_ROW, unable to obtain exclusive access to this record or 1 records: <ID_REMOVED>: []

Class.rh2.PS_Run_Utility.turnOffValidationRules: line 212, column 1 Class.rh2.PS_Parent_Record_WrapperClass.updateParents: line 206, column 1 Class.rh2.PS_Parent_Record_WrapperClass.updateParentRecords: line 154, column 1 Class.rh2.PS_Rollup_Helper.addAndThenClearRollupContextParentFields: line 614, column 1 Class.rh2.PS_Rollup_Helper.performSync: line 524, column 1 Class.rh2.ParentUtil.performTriggerRollups: line 213, column 1 Trigger.rh2.PS_Account: line 7, column 1","errorCode":"CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY","fields":[]}]

Based on the stacktrace it seems that something is having a lock in a database. When we get the 400 back, we do a retry. I can see that for one issue we, at the 6th retry, it seems to successfully have created the account. However, it seems that for every retry an account is created in Salesforce and hence we are ending up with duplicate accounts, so our id is linked to multiple accounts.

I'm trying to understand:

  1. Why do we get a 400 back (so why is the parent locked?)

  2. How should we perform our error handling for this scenario? I'm trying to figure out how we can be resillient enough and with a good retry logic without creating duplicates. Since it is a POST it is ok that the endpoint is not idempotent, however, since we do not get a accountId back in the response, I'm not sure have to make it idempotent on our side

Best regards Hans-Christian

  • 1
  • Hmm, not really, I'm more looking how to make the error handling of the REST API idempotent and have resillent error handling when using the API. I know very little about the Salesforce internal – Hans-Christian Göranson Jul 13 '21 at 19:36
  • Or it gives some pointers that we might have a big hierarchy with many children - so far so good. I will ask my Salesforce specialist if they can give some hints. However, I still would like to understand how I as a client should handle the error and why the 400 response has created an account. – Hans-Christian Göranson Jul 13 '21 at 19:49
  • I can see that at the 6th retry, it seems to successfully have created the account contradicts it seems that for every retry an account is created in Salesforce – identigral Jul 13 '21 at 19:51
  • 2
    rh2 is the namespace of the Rollup Helper app. (You can see this in Setup > Installed Packages.) There is probably some contention between your insert automation and one or more Rollup Helper jobs. You may need to open a case with the vendor. – David Cheng Jul 13 '21 at 21:45
  • 1
    Thanks for all feedback. @identigral – I can see my description is a bit unclear. I meant that after 6 retries I get a successful response back which contains the SF account id in the response compared to the failed responses which only contains an error msg. However, since the SF account is created even though the request fails, I will need to change how I interact with the API. The current logic is that we retry for error responses with the assumption that the SF account was not created in the failure scenario which I will need to change. Thanks for the help, I think I got what I need – Hans-Christian Göranson Jul 14 '21 at 06:40
  • Another thought, anyone knows if it is possible to rollback the transaction inside the SalesForce system when the upsert fails? So, if a failure occurs during the handling of the HTTP request, rollback the whole transaction and hence do not creates a SF account. – Hans-Christian Göranson Jul 14 '21 at 06:59
  • After talking to our salesforce specialist we solved this but omiting a parent id in the create request and hence avoid the rollup action in the same operation as the account creation. This will reduce the issue for now. However, I'm still wondering why do we get a 400 back? in this case maybe a 423 would be better. Can the rollup action be decoupled from the create account? so run the roll up async in a background process. E.g, create account returns 2xx then the rollup can happen in the background. Is it a general approach to to have this kind of non-tranasaction approach behind the SF API? – Hans-Christian Göranson Jul 16 '21 at 06:09

0 Answers0