1

I'm experiencing the following error in our Production instance:

Error: Invalid Data. Review all error messages below to correct your data. Apex trigger AcctMlstnUpdt caused an unexpected exception, contact your administrator: AcctMlstnUpdt: execution of AfterUpdate caused by: System.EmailException: SendEmail failed. First exception on row 0; first error: INVALID_CROSS_REFERENCE_KEY, invalid cross reference id: []: Trigger.AcctMlstnUpdt: line 23, column 1

The trigger works fine and has 100% code coverage in the Sandbox - Trigger & test class is as follows:

trigger AcctMlstnUpdt on Account (after insert, after update) {

for (Account acct : Trigger.New) {

    String[] toAddresses = new String[] {acct.Lead_Email__c}; 
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();

    mail.setTargetObjectId(acct.OwnerID);
    mail.setToAddresses(toAddresses);
    mail.setSenderDisplayName('Home Captain Realty Update');
    mail.setUseSignature(false);
    mail.setBccSender(true);
    mail.setSaveAsActivity(false);

    if(acct.Milestones__c == 'In Contract, pre-mortgage') {
        mail.setTemplateId('00X18000000M2zL');
        Messaging.SendEmailResult [] r = 
            Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});   
    } 

    if(acct.Milestones__c == 'In Contract, Mortgage Commitment Received') {
        mail.setTemplateId('00X18000000M2zQ');
        Messaging.SendEmailResult [] r = 
            Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});   
    } 

    if(acct.Milestones__c == 'Closed/Archived') {
        mail.setTemplateId('00X18000000M2zV');
        Messaging.SendEmailResult [] r = 
            Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});   
    }  
} }

@isTest private class TestAcctMlstnUpdt {

public TestMethod static void CallAcctMlstnUpdt() { 

    Account myAcct = new Account();

    myAcct.Name = 'Test_Account';
  myAcct.Lead_First_Name__c = 'John';
  myAcct.Lead_Last_Name__c = 'Doe';
    myAcct.Lead_Email__c = '[email protected]';

    try {             insert myAcct;
    }
    catch (Exception ex) {
        System.debug('A DML error has occurred in TestAcctMlstUpdt: ' + ex.getMessage());
        return;
    }

    System.assertEquals('Test_Account', myAcct.Name);        
    System.assertEquals('John', myAcct.Lead_First_Name__c);
    System.assertEquals('Doe', myAcct.Lead_Last_Name__c);
    System.assertEquals('[email protected]', myAcct.Lead_Email__c);

    myAcct.Milestones__c = 'In Contract, pre-mortgage';

    try {             update myAcct;
    }
    catch (Exception ex) {
        System.debug('A DML error has occurred in TestAcctMlstUpdt: ' + ex.getMessage());
        return;
    }

    System.assertEquals('In Contract, pre-mortgage', myAcct.Milestones__c);


    myAcct.Milestones__c = 'In Contract, Mortgage Commitment Received';       update myAcct;
    System.assertEquals('In Contract, Mortgage Commitment Received', myAcct.Milestones__c);


    myAcct.Milestones__c = 'Closed/Archived';         update myAcct;
    System.assertEquals('Closed/Archived', myAcct.Milestones__c);        
} }

2 Answers 2

3

The reason could be the hardcoded id's you are using for email templates. As the id change from environment to environment, it is always recommended not to hardcode any id in code. You should retrieve id of email templates (fire soql query on emailtemplate) to retrieve production environment id for the email templates and use them.

1
  • Anshul, I agree - updating my code now. Thanks very much :)
    – cpqcrew
    Jun 5, 2015 at 16:56
0

Updated Trigger (solved issue):

trigger AcctMlstnUpdt on Account (after insert, after update) {

for (Account acct : Trigger.New) {

    String[] toAddresses = new String[] {acct.Lead_Email__c}; 
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();

    mail.setTargetObjectId(acct.OwnerID);
    mail.setToAddresses(toAddresses);
    mail.setSenderDisplayName('Home Captain Realty Update');
    mail.setUseSignature(false);
    mail.setBccSender(true);
    mail.setSaveAsActivity(false);

    if(acct.Milestones__c == 'In Contract, pre-mortgage') {
        EmailTemplate template = [Select Id from EmailTemplate where Name = 'Account Milestone - In Contract, pre-mortgage'];
        mail.setTemplateId(template.Id);
        Messaging.SendEmailResult [] r = 
            Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});   
    } 

    if(acct.Milestones__c == 'In Contract, Mortgage Commitment Received') {
        EmailTemplate template = [Select Id from EmailTemplate where Name = 'Account Milestone - In Contract, Mortgage Commitment Received'];
        mail.setTemplateId(template.Id);
        Messaging.SendEmailResult [] r = 
            Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});   
    } 

    if(acct.Milestones__c == 'Closed/Archived') {
        EmailTemplate template = [Select Id from EmailTemplate where Name = 'Account Milestone - Closed/Archived'];
        mail.setTemplateId(template.Id);
        Messaging.SendEmailResult [] r = 
            Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});   
    }  
}

}

2
  • Can you explain more what the actual fix was? The resolved code is certainly nice, but some more human-parseable information about the ultimate fix can help others in the future with similar issues. Jun 7, 2015 at 22:43
  • I believe actually reading the post from top to bottom and reviewing the code would easily reveal that the answer suggested by Anshul was implemented. The hard coding of the template id was removed, and a SOQL query implemented to determine same based upon the template name.
    – cpqcrew
    Jun 9, 2015 at 13:21

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .