[SalesForce] Exception in Database.save result in trigger context

1) In my opportunityLineitemtrigger, I have a method which updates the opportunity.

system.debug('######');
database.saveresult [] rst = database.update(oppList,true);
system.debug('######'+rst);

While updating the opportunity, it calls the before update trigger event of opportunity. In that before update trigger method, I have used an add error method to throw an error message for some of the records which met the criteria

for(Opportunity opp : newList){
                    if(opp.RecordTypeId != SEUtility.getRecordTypeId(SEUtility.OPP_RECTYPE))
                    {       opp.addError(Label.Record_type_not_allowed_to_change);
                        }  
                    }

Once the before update triggers fire with adderror , I dont get anything in database.saveresult in the above code , the debug line system.debug('######'+rst); doesn't gets executed , on checking the logs I see the adderror exception.

Is this is as per salesforce guidelines, since I know when we used database.saveresult it will show the records which got failed and which got succeeded. If for adderror some records failed why cant I get that details in the saveresults.

2) Secondly I see a big error message in RED as

Review all error messages below to correct your data. Apex trigger
OpportunityLineItem caused an unexpected exception, contact your
administrator: OpportunityLineItem: execution of AfterUpdate caused
by: System.DmlException: Update failed. First exception on row 0 with
id 0061p0000iuy7AAQ; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION,
Fill the values as per the standards: []:
Class.OpportunityLineItemTriggerHandler.updatesalesvalue: line 95,
column 1

If I am using adderror , it should have been the single line custom error message which i had defined but why so many details shown on UI ?

Best Answer

  1. You're passing true as the second parameter (allOrNone) to Database.update(). What you're observing is the documented behavior for that situation:

... using the Database class method, you can specify whether or not to allow for partial record processing if errors are encountered. You can do so by passing an additional second Boolean parameter. If you specify false for this parameter and if a record fails, the remainder of DML operations can still succeed. Also, instead of exceptions, a result object array (or one result object if only one sObject was passed in) is returned containing the status of each operation and any errors encountered. By default, this optional parameter is true, which means that if at least one sObject can’t be processed, all remaining sObjects won’t and an exception will be thrown for the record that causes a failure.

(See DML Statements vs. Database Class Methods)

When you pass true, you get an exception thrown if any record fails, rather than a set of Database.SaveResult records.

  1. The error message essentially gets wrapped in a DmlException which yields this rather user-unfriendly stack trace message. If you want to fix that, you'd need to wrap your DML code at the top level (in your page controller) with a try/catch block and generate a more friendly page message. Alternately, pass false for allOrNone as above, and synthesize a message to the user from the result messages you get back. (See Database.SaveResult)
Related Topic