[SalesForce] How to show exception message in lightning without stacktrace

Background:

  1. I have trigger on Opportunity object for after delete event and it updates a field Number_of_Opps__c on Account object.
  2. There is a validation rule on Account object for the same field firing if Number_of_Opps__c = 0
  3. When I am deleting Opportunity record from custom lightning component,trigger on Opportunity is running and it is updating field Account.Number_of_Opps__c to zero but validation rule on Account object is rejecting this update.

Problem:
When this happens, I need to show user a simple and clean message without stacktrace of trigger line number.

My observation:

  1. If Apex trigger is not involved then it is displaying clean message to the user without stacktrace of line numbers.

I have gone through Error Handling Best Practices for Lightning and Apex but no luck.

As a last resort, I have tried to use regex to replace everything after : [] and even that is not working, maybe something wrong with my regex.

Here is the code:

HelloWorld.cmp

<aura:component controller="HelloWorldApexController">
    <button onclick="{!c.delete}">Delete</button>
</aura:component>

HelloWorldController.js:

({
    delete: function(cmp) {
        var action = cmp.get("c.deleteOpp");
        action.setCallback(this, function(result) {
            if(result.getState() == 'SUCCESS'){

            }
            if(result.getState() == 'ERROR'){
                var toast = $A.get("e.force:showToast");
                if(toast){
                    toast.setParams({
                        "title": "Error",
                        "message": result.getError()[0].message
                    });
                }
                toast.fire();
            }
        });
        $A.enqueueAction(action);
    }
})

HelloWorldApexController.cls:

public with sharing class HelloWorldApexController {

    @AuraEnabled
    public static void deleteOpp(){
        Opportunity oppObj = new Opportunity(Id='006370000025PVY');

        try{
            delete oppObj;  
        }catch(DmlException e){
            throw new AuraHandledException(e.getDmlMessage(0).replaceFirst(': \\[\\] .*',''));
        }
    }
}

OpportunityTrigger.trigger:

trigger OpportunityTrigger on Opportunity (after delete) {

    if(trigger.isAfter && trigger.isDelete){
        Account accObj = new Account(Id = '00137000002KXpBAAW',Number_of_Opps__c = 0);
        update accObj;
    }

}

Note: For the sake of simplicity, I have hardcoded Ids and did not bulkify the trigger.

Screenshot:

enter image description here

Best Answer

Even if you can't control other people's code, you can control your own. You should be able to do this:

Database.SaveResult result = Database.delete(oppObj, false);
if(!result.isSuccess()) {
  throw new AuraHandledException(result.getErrors()[0].getMessage());
}

You will no longer get DmlException messages, but instead get a nice interface to render an error with. If you still need to contend with other types of errors (e.g. a NullPointerException), you can wrap up the entire thing and rethrow:

try {
  Database.SaveResult result = Database.delete(oppObj, false);
  if(!result.isSuccess()) {
    throw new AuraHandledException(result.getErrors()[0].getMessage());
  }
} catch(Exception e) {
  throw new AuraHandledException(e.getMessage());
}
Related Topic