无法从触发器捕获异常(Custom + Standard)

时间:2022-10-28 14:33:12

Please consider the below scenario:

请考虑以下情况:

  1. I have an Application__c object.
  2. 我有一个Application__c对象。

  3. 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.
  4. 我有一个触发器(为简单起见,直接在触发器中编码),如果记录名称为Error则会执行一项操作,然后抛出异常。


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:

    现在我在代码下运行:

    无法从触发器捕获异常(Custom + Standard)

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

现在注意catch语句没有执行,意味着系统无法捕获异常。这是致命错误。

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.

让我知道你们是否曾经遇到过这样的情况,如果你们做了什么以确保它被正确抓住了。

1 个解决方案

#1


2  

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.

现在大约一年(如果不是更长时间),尝试捕获跨越触发事务已异常不可靠。前一段时间,您曾经能够捕获正确类型的异常(例如,NullPointerException就是这样),而我注意到去年或今年早些时候触发器中的任何异常都将转换为DmlException,原来的错误丢失了。现在,似乎触发器中的任何未处理的异常都会立即终止事务,日志的状态代码显示该异常。

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.

我将在salesforce.com上与一些人进行核实并提出这个问题,看看它是否是故意更改,或者是否需要记录错误。目前,我能为您提供的最佳建议是:除非您有意尝试终止交易,否则不要允许例外情况留下您当前的代码上下文(例如触发器)。每个代码单元都应负责处理自己的异常。如果需要报告错误,请始终使用addError方法将错误报告回调用上下文。

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.

无论如何,这确实是最好的做法。例外应该是例外(或理想情况下,从不),如果它们确实发生,它们应尽可能靠近源处理。始终尝试编写不会生成异常的代码,尤其是NullPointerException,ListException,QueryException,MathException和TypeException。所有这些例外都很容易避免和/或可以在它们可能发生的地方附近处理。


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.

尽管执行匿名代码不起作用,但单元测试仍然通过。我确信这是一个错误,我会尽我所能让你看看这个。

#1


2  

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.

现在大约一年(如果不是更长时间),尝试捕获跨越触发事务已异常不可靠。前一段时间,您曾经能够捕获正确类型的异常(例如,NullPointerException就是这样),而我注意到去年或今年早些时候触发器中的任何异常都将转换为DmlException,原来的错误丢失了。现在,似乎触发器中的任何未处理的异常都会立即终止事务,日志的状态代码显示该异常。

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.

我将在salesforce.com上与一些人进行核实并提出这个问题,看看它是否是故意更改,或者是否需要记录错误。目前,我能为您提供的最佳建议是:除非您有意尝试终止交易,否则不要允许例外情况留下您当前的代码上下文(例如触发器)。每个代码单元都应负责处理自己的异常。如果需要报告错误,请始终使用addError方法将错误报告回调用上下文。

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.

无论如何,这确实是最好的做法。例外应该是例外(或理想情况下,从不),如果它们确实发生,它们应尽可能靠近源处理。始终尝试编写不会生成异常的代码,尤其是NullPointerException,ListException,QueryException,MathException和TypeException。所有这些例外都很容易避免和/或可以在它们可能发生的地方附近处理。


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.

尽管执行匿名代码不起作用,但单元测试仍然通过。我确信这是一个错误,我会尽我所能让你看看这个。