function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
KlivingstonKlivingston 

System.NullPointerException: Attempt to de-reference a null object:

Hi everyone.

Can you please help me to fix this error: I have a trigger that would send an email alert to new AssignedTo user. But it through an error if the Site Defect is a new record. in other word when the Trigger.old[0].Assigned_To__c is empty. 

here is the code:

trigger SendEmailAlertToAssignedTo on Site_Defects__c (after insert, before update) { // I have the error message here

    if(Trigger.new[0].Assigned_To__c != Trigger.old[0].Assigned_To__c ) {
       
            //Sending Mail
            Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage() ;
          
                //Setting user email in to address
            String userName = Trigger.new[0].Assigned_To__c;
             
            User AT = [Select Email From User where id= : userName ]; 
            String userEmail = AT.Email;
          
          
            //String email = Trigger.new[0].RegionalManager__c;
            String[] toAddresses = new String[] {userEmail} ;
          
            // Assign the addresses for the To and CC lists to the mail object
            mail.setToAddresses(toAddresses );
            mail.setToAddresses(MyEmail);
          
            //Email subject to be changed
            mail.setSubject('THIS IS A TEST. Site Defect Owner Changed');
            String body = AT.Email+'The owner of Site Defect ' + trigger.Old[0].Name +' has been changed <br> <br>'+
            'Regards <br> ';
            //Body of email
            mail.setHtmlBody(body);
          
            //Sending the email
            Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
            }
}

Thank you. 
Florian HoehnFlorian Hoehn
First off: bulkify your trigger:

for(Integer index = 0; index < Trigger.new.size(); index++) {
  if(Trigger.new[index].Assigned_To__c != Trigger.old[index].Assigned_To__c ) {
    ...
  }
}

then: have you thought of the execution order of assignment/workflow rules and the trigger? Maybe this field IS still empty when the trigger fires and gets filled later on? Just a few thoughts.

Hope this already helps!

Florian
Damien Phillippi033905702927186443Damien Phillippi033905702927186443
Trigger.old will be null on insert triggers because it didn't exist before the insert.
KlivingstonKlivingston
Hi guys

Thanks for your comments. I managed to get the code right and the trigger is working fine, I wonder how I could make it more efficient, here is the code:

trigger SendEmailAlertToAssignedTo on Site_Defects__c (after insert, before update) {

for(Site_Defects__c sd:Trigger.new){
  /Sending Mail
  essaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage() ;

  /Setting user email in to address
  tring userName = Trigger.new[0].Assigned_To__c;

  ser AT = [Select Email From User where id= : userName ];
  tring userEmail = AT.Email;

  /String email = Trigger.new[0].RegionalManager__c;
  tring[] toAddresses = new String[] {userEmail} ;
  
  / Assign the addresses for the To and CC lists to the mail object
  mail.setToAddresses(toAddresses );
  mail.setToAddresses(MyEmail);

  //Email subject to be changed
  mail.setSubject('THIS IS A TEST. Site Defect Owner Changed');
  String body = ' The Site Defect ' + trigger.New[0].Name +' has been    assigned to you.<br> <br>'+
  Rgards <br>';
  Body of email
  il.setHtmlBody(body);

  Sending the email
  ssaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
  }
}


Florian Hoehn; I thought to make a bulk email trigger you must use List<>?

Thanks
Damien Phillippi033905702927186443Damien Phillippi033905702927186443
He essentially was telling you to do the same thing you already did with your loop.  The loop you used is better though because its specifically made for iterating over a list.

You have a severe issue with your trigger.  If there is more than 1 Site_Defect__c at a time, your trigger could potentially email someone incorrectly because of your line:
<pre>
String userName = Trigger.new[0].Assigned_To__c;
</pre>
This will always grab only the first records Assigned_To__c instead of working in bulk.  Instead of:
<pre>
Trigger.new[0].
</pre>
You should be using the following in place of all of those.
<pre>
sd.
</pre>

Before your loop you should get the entire set of userIds and query for all of them at once and place into a Map:
<pre>
Map<Id, User> userMap = new Map<Id, User>{[SELECT Email FROM User WHERE Id IN :userIds]};
</pre>

then you can grab the user you need inside your loop by:
 <pre>
User AT = userMap.get(sd.Assigned_To__c);
</pre>

Another difference I would change is:
<pre>
Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
</pre>

you should instead add it to a list then send the whole list.
<pre>
List<Messaging.SingleEmailMessage> emails = new List<Messaging.SingleEmailMessage>();

for (Site_Defects__c sd:Trigger.new)
{
  //Do your work here
  ...
  emails.add(email);
}
Messaging.sendEmail(emails);
</pre>
Damien Phillippi033905702927186443Damien Phillippi033905702927186443
Also, keep in mind that the way you have your trigger, it won't always work correctly.  It will only work correctly for 1 record at a time until you do the fixes I described above.
KlivingstonKlivingston

Hi Damien

Thanks for your reply, I am working on the first part of your comment. The SFDC shows an error :

by: System.NullPointerException: Attempt to de-reference a null object: Trigger.SendEmailAlertToAssignedTo: line 14, column 1

I am not sure where I am doing wrong. can you please help with this:


Thanks


trigger SendEmailAlertToAssignedTo on Site_Defects__c (after insert,  before update) {
 
  Map<Id, User> userMap = new Map<Id, User>([SELECT Email FROM User WHERE id IN :Trigger.newMap.keySet()]);      
 
  for(Site_Defects__c sd:Trigger.new){
        //Sending Mail
               Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage()  ;
               
                //Setting user email in to address
                //String userName = sd.Assigned_To__c;
                  
                User AT = userMap.get(sd.Assigned_To__c);
                //System.debug(AT);
                String userEmail = AT.Email;                 //Error
           
                //String email = Trigger.new[0].RegionalManager__c;
                String[] toAddresses = new String[] {userEmail} ;
                string[] MyEmail = new string[] {'ghasem.rahmani@contractor.p66.com'};
               
                // Assign the addresses for the To and CC lists to the mail object
                mail.setToAddresses(toAddresses );
                mail.setToAddresses(MyEmail);
               
                //Email subject to be changed
                mail.setSubject('THIS IS A TEST. Site Defect Owner Changed');
                String body = ' The Site Defect ' + trigger.New[0].Name +' has been assigned to you.<br> <br>'+
                'Regards <br>';
                //Body of email
                mail.setHtmlBody(body);
               
                //Sending the email
                Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });

            }
}

damienphillippi1.3915403128946355E12damienphillippi1.3915403128946355E12
Before this line:

<pre>
Map<Id, User> userMap = new Map<Id, User>([SELECT Email FROM User WHERE id IN :Trigger.newMap.keySet()]);
</pre>

You need to build a Set of userIds by looping through your Trigger.new  You then use that set of Ids to build the map
<pre>
Set<Id> userIds = new Set<Id>();
for (Site_Defects__c defect: Trigger.new)
{
  userIds.add(defect.Assigned_To__c);
}
</pre>