You have the following line inside the try block.`
List<Database.SaveResult> results= Database.update(listUserDeactivate,false);
The database.update method takes in two parameters as in your code:
- The sobject or collection of sobjects to perform the update on
- allOrNone - This parameter is set to false to allow partial success
The second parameter called allOrNone is exactly what differentiates the database.update from update. While using the update method and performimg a DML like
update listUserDeactivate;
Then even when the update of any one of the records in the list fails - the whole update process fails and a DML exception is thrown. This would have been in your case too have you written the code as
List<Database.SaveResult> results= Database.update(listUserDeactivate,true);
This sets the allOrNone parameter to true which implies system either updates all the records(i.e. when no individual record update fails) or updates no record(i.e. the scenario where at least the update of one record in the list fails). So what is happening in you case is that because allOrNone is set to false, partial success of the update operation is allowed and that is what exactly happened. Not all records in the list were updated successfully and due to your way of using database.upsert NO EXCEPTION was thrown.
But logs capture everything in finer detail, including the DML update situation of every individual record. Hence the failure is logged in the debug logs. Thanks
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.
Best Answer
Sorry to say, but System.UnexpectedException can generally not be caught. That's by definition, e.g. see here
What you could do is criticize that the exception thrown under these circumstances is of this type. Or maybe this is what you wanted to do in the first place?!