If I have some code doing DML which runs a trigger, and then that trigger throws an unhandled exception, how can I get the real cause of the problem?
For example, suppose I have a really dumb trigger:
trigger AccountTrigger on Account (after insert) {
insert new Lead();
}
This will always fail because it's not specifying the required fields for Lead.
Then, I write a test to see whether or not I can catch the cause of the exception to be REQUIRED_FIELD_MISSING:
@IsTest
private class ChainedTriggerErrorTest {
static Account toInsert = new Account(Name = 'ACME');
@IsTest
static void allOrNothingFalse() {
Database.SaveResult result = Database.insert(toInsert, false);
System.assertEquals(1, result.getErrors().size());
Database.Error theError = result.getErrors()[0];
System.assertEquals(StatusCode.CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, theError.getStatusCode());
System.assert(theError.getMessage().contains(StatusCode.REQUIRED_FIELD_MISSING.name()));
System.debug(theError.getMessage());
}
@IsTest
static void tryCatch() {
try {
insert toInsert;
} catch (DmlException e) {
System.assertEquals(StatusCode.CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, e.getDmlType(0));
System.assertEquals(null, e.getCause());
System.assert(e.getMessage().contains(StatusCode.REQUIRED_FIELD_MISSING.name()));
System.debug(e.getMessage());
}
}
}
All of those assertions pass i.e. both methods of trapping the errors only reveal on cause, and that cause is CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY. So, you're stuck with searching the text body of the message to see what the real cause is.
It seems insane that e.getCause()
returns null
when the debug of e.getMessage()
is:
Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, AccountTrigger: execution of AfterInsert
caused by: System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [LastName, Company]: [LastName, Company]
Trigger.AccountTrigger: line 7, column 1: []
(Emphasis mine)
Obviously, this is a bit of a fake scenario, but the real-world problem could be something like catching a row lock error. I want to catch it at the top-level and just try again later. And I'd rather do that in a better way than scraping the error message. Is there any better way?