0

How should I efficeintly handle addError() errors when using Database.update(obj[],false) from the code?

They are all failing as they are hitting addError() in all of the 3 attempts. Is Database.update(obj[], false) not suitable with addErrors()?

After working on the issue for quite some time, I decided to use a boolean to ignore the validation errors so as not to encounter addError() from the trigger. Is this the correct approach?

Let's take an example of 5 records out of which the first 3 consecutive records throw addError().

  • Database.update(obj[],false) First attempt: hits the error at the 1st record and deletes it from the array of records for retrying. The array for the retrial has 4 records out of which 2 would fail.
  • Database.update(obj[],false) Second attempt: Fails again at the first record and deletes it. The array now has 3 records out of which 1 would fail again.
  • Database.update(obj[],false) Third attempt: Fails again at the first record and rollsback the updates on the whole array as Database.update(obj[], false) only tries 3 attempts before failing.
  • 1
    Your question is not very clear. Please edit your post to include a specific, simple example of what's going on. Only records which have had an error added to them should fail to save. – Adrian Larson Feb 22 '18 at 0:17
  • Please include sample code in your question. – DavidSchach Feb 22 '18 at 0:26
  • I have edited my post to add detail. The code is in different places & huge to copy+paste but the example that I have detailed is the issue I am facing. – Shalini SF Feb 22 '18 at 0:32
1

SObject.addError accumulates all errors in the same trigger context. In reality, properly written triggers would each add their errors, and there would be ideally at most one retry. If it's not working that way, there's a problem with your code. Here's a trivial example that you can copy-paste into a developer org to prove that addError certainly works with more than 3 records:

trigger prevent1358 on account (before insert) {
  if(Trigger.new.size() == 8) {
    Trigger.new[0].addError('You have been blocked.');
    Trigger.new[2].addError('You have also been blocked.');
    Trigger.new[4].addError('Sorry. You are BLOCKED.');
    Trigger.new[7].addError('So sorry. You. Are. Blocked. Ha!');
  }
}

Then, in execute anonymous:

Account[] records = new Account[8];
for(Integer index = 0; index < 8; index++) {
  records[index] = new Account(Name='Account '+(index+1));
}
Database.SaveResult[] results = Database.insert(results, false);
System.assertEquals(false, results[0].isSuccess());
System.assertEquals(false, results[2].isSuccess());
System.assertEquals(false, results[4].isSuccess());
System.assertEquals(false, results[7].isSuccess());

This behavior is true even if the addError messages occur in different triggers (but you shouldn't have different triggers, using the One Trigger Per Object best practice).

Do not write your code that only checks one error at a time. The following trigger will break if you have multiple errors:

trigger preventRecord0 on account (before insert) {
  Trigger.new[0].addError('Blocking the first record.');
}

Account[] records = new Account[8];
for(Integer index = 0; index < 8; index++) {
  records[index] = new Account(Name='Account '+(index+1));
}
// Too many retry errors
Database.SaveResult[] results = Database.insert(results, false);

While it may make sense to try and break early on an error, or only do one type of validation at a time, you're actually setting yourself up for failure. Perform all of your validations once and in the same location.

  • Thanks for the detailed answer @sfdcfox. Do you suggest that addError() be coded from one single spot after going through all the validation checks?Please suggest how to efficiently code bulk trigger addError(), please. – Shalini SF Feb 22 '18 at 2:43
  • @ShaliniSF No, I'm saying that you should do all of your validation checks in one place. Notice how in the first example, I add four different errors on four different records (Good Idea), while in the second example, I'm basically just checking one record instead of all of them at once (Bad Idea). You can have as many validations as you need, but do them all in the same trigger, and all at once. Do not use break, continue, or any other designs that abort early; all of the errors for all of the fields/records you're checking should be added at once. – sfdcfox Feb 22 '18 at 3:03
  • Sfdcfox, Would you be able to reproduce the error which prohibits the saving of even a single record from your example. I am not encountering the error that I had before even after many attempts & without changing any error handling code. I would like to get to the bottom of this concept or can you redirect me to any link that you may be aware of covering the efficient usage of bulk triggers, addError & Database.update(obj[],false) concepts together? Thanks in advance. – Shalini SF Mar 1 '18 at 2:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.