5

Please consider the below scenario:

  1. I have an Application__c object.
  2. I have a trigger on that (for simplicity, coded directly in trigger) which does one thing if the record name is Error then throws exception.

trigger ApplicationTrigger on Application__c (before insert, after update){

        if(trigger.new[0].Name == 'Error'){
            Application__c application;
            System.debug(application.Name);
        }
}
  1. Now I am running below code:

    enter image description here

Now notice the catch statement is not executing, means system was not able to catch the exception. It came as the Fatal Error.

This is kind of a big issue where if there is null pointer or any other exception in trigger and exception handling code will not be able to do anything. Not even logging since it never reaches to catch block.

Let me know if you guys ever faced such situation and if yes what you did to make sure that it is properly caught.

8

Try-catch spanning trigger transactions has been exceptionally unreliable for about a year now (if not longer). Some time ago, you used to be able to catch the correct type of exception (e.g. a NullPointerException would be just that), while I noticed either last year or early this year that any exception in a trigger would be converted to a DmlException instead, the original error lost. Now, it appears that any unhandled exception in a trigger immediately terminates the transaction, with the status code for the log showing that exception.

I'm going to check with some people over at salesforce.com and bring this up, see if it's an intentional change, or if there needs to be a bug logged. For now, the best advice I can offer you is this: do not allow exceptions to leave your current code context (e.g. a trigger) unless you're intentionally trying to terminate the transaction. Each code unit should be responsible for handling its own exceptions. If you need to report an error, always use the addError method to report the error back to the calling context.

This is really a best practice anyways. Exceptions should be exceptional (or ideally, never), and when/if they do happen, they should be handled as close to the source as possible. Always try to write code that won't generate exceptions, particularly NullPointerException, ListException, QueryException, MathException, and TypeException. All of these exceptions are easily avoidable and/or can be handled in the immediate vicinity of where they can occur.


Edit: I built a unit test for this, and the code worked as expected. Here's the trigger and unit test for context:


trigger q232645 on Lead (before insert) {
    if(Trigger.new[0].LastName == 'Exception') {
        Lead record;
        // This line here generates a NullPointerException...
        record.LastName = 'Test';
    }
}

@isTest class q232645Test {
    @isTest static void test() {
        try {
            insert new lead(LastName='Exception');
            System.assert(false, 'Should not reach here; trigger should throw exception.');
        } catch(Exception e) {
            System.debug('We should see this in the logs.');
            return;
        }
        System.assert(false, 'We should not get this far because of the return statement.');
    }
}

This unit test passes, despite the execute anonymous code not working. I'm convinced this is a bug, and I'll do my best to have some one look in to this for you.


Edit 2:

This is intended behavior, according to this help article (thanks, @KiranMachhewar!). You must not allow exceptions to escape the trigger context.

|improve this answer|||||
  • But I am not completely aligned with the concept of handling exception as close to the source as possible, because here just for example I used null pointer. But in my application/code base I use Custom Exception heavily to stop the execution like when I don't find custom setting record or some data is required other wise there is no point in going further in code and such failure/exception situations code be anywhere in code. So exception makes most sense, but with the above problem looks like I am not able to log or properly notify to the user about the error. – Kiran Machhewar Sep 16 '18 at 2:10
  • Let me add more to this, I have a web service which is called from third party and I make sure that I give the error status code if the webservice code gets an exception and comes in catch block and I return the message also. Sometimes third party system could miss some values or sufficient data might not be present in my side only so I use Exceptions, it worked out really well, I had full confidence that no matter what (except uncatchable exceptions), I would be able to log the message and return the proper error but now as the control is not coming in catch, I am not respond error to other – Kiran Machhewar Sep 16 '18 at 2:13
  • @KiranMachhewar Exceptions should be used as sparingly as possible for performance reasons. There are times to use them, but definitely not to try and transmit data across a DML-transaction barrier. – sfdcfox Sep 16 '18 at 2:13
  • -- continue other system and nor I am able to do my custom logging. Again thank you for looking into this. – Kiran Machhewar Sep 16 '18 at 2:14
  • 1
    When I raised case with salesforce and talked to them they said its not a bug and it is implemented as per design and for this scenario they gave this workaround help.salesforce.com/… – Kiran Machhewar Oct 12 '18 at 23:04

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.