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
Gab SilvermotionGab Silvermotion 

moved a trigger to another SF instance, now i have a "System.NullPointerException: Attempt to de-reference a null object" error

Hello!

I have this apex code that changes automatically the stage of the opportunity based on the activities made in the opportunities. 

I move it from one SF instance to another using packages. It works as intended in the source instance, but in the target instance it give me the following error

Apex trigger nubik_OpportunityAutoStage caused an unexpected exception, contact your administrator: nubik_OpportunityAutoStage: execution of BeforeUpdate caused by: System.NullPointerException: Attempt to de-reference a null object: Trigger.nubik_OpportunityAutoStage: line 52, column 1

anyone knows why?


here is the code of the trigger: line 52 is this one :  if(t.Type.toLowerCase().startsWith('call')) 


// This trigger set the stage of an opp based on 4 actions ;
// 1. Email Counter
// 2. Phone Calls
// 3. Visits Sales Office (walk-in counter)
// 4. Underwriting (see the closing_details__c object)
trigger nubik_OpportunityAutoStage on Opportunity (before update, before insert) {

map<string, list<Task>> taskMap = new map<string, list<Task>>();
map<string, list<Event>> eventMap = new map<string, list<Event>>();

if (trigger.isUpdate)
{
  for(Task t : [Select Id, Status, WhatId, Type, Subject from Task where WhatId in : Trigger.newMap.keyset()])
  {
   if (!taskMap.containsKey(t.WhatId))
    taskMap.put(t.WhatId, new list<Task>());
  
   taskMap.get(t.WhatId).add(t);
  }
 
  system.debug('nubik_OpportunityAutoStage taskMap ' + taskMap);
 
  for(Event e : [Select Id, WhatId, Type, Subject from Event where WhatId in : Trigger.newMap.keyset()])
  {
   if (!eventMap.containsKey(e.WhatId))
    eventMap.put(e.WhatId, new list<Event>());
  
   eventMap.get(e.WhatId).add(e);
  }
 
  system.debug('nubik_OpportunityAutoStage eventMap ' + eventMap);
 
  for(string oppId : trigger.newMap.keyset())
  {
   system.debug('nubik_OpportunityAutoStage oppId ' + oppId );
  
   integer question = 0;
   integer walkIn = 0;
   integer email = 0;
   integer call = 0;
  
   if (taskMap.get(oppId) != null)
   {
    system.debug('nubik_OpportunityAutoStage oppId relate tasks ' + taskMap.get(oppId));
    for(Task t : taskMap.get(oppId))
    {
     if (t.Type != null && t.Type == 'Question' && t.Status != 'Completed')
      question++;
     
     
     if(t.Type.toLowerCase().startsWith('call'))
      call++;
          
          if(t.Type.toLowerCase().startsWith('email'))
           email++;
          
         
    }
   }
  
   if (eventMap.get(oppId) != null)
   {
    for(Event e : eventMap.get(oppId))
    {
     if (e.Type != null && (e.Type == 'Walk-In' || e.Type.contains('Meeting')))
      walkin++;
    }
   }
  
   system.debug('nubik_OpportunityAutoStage oppId ' + oppId );
  
   Trigger.newMap.get(oppId).Question_Counter__c = question;
   Trigger.newMap.get(oppId).Email_Attemps_Counter__c = email;
   Trigger.newMap.get(oppId).Walking_Attemps_Counter__c = walkin;
   Trigger.newMap.get(oppId).Call_Attemps_Counter__c = call;
  }
}

map<string, Closing_Detail__c> closingMap = new map<string, Closing_Detail__c>();
map<string, VIP__c> vipMap = new map<string, VIP__c>();

if (trigger.isUpdate)
{
  for (Closing_Detail__c tempClosing : [Select Id, Opportunity__c, Bank_Approval__c , Bank_Refusal__c from Closing_Detail__c  where Opportunity__c in : trigger.newMap.keyset()])
  {
   closingMap.put(tempClosing.Opportunity__c, tempClosing);
  }
 
  for (VIP__c tempVIP : [Select Id, Opportunity__c, Canceled__c from VIP__c  where Opportunity__c in : trigger.newMap.keyset()])
  {
   vipMap.put(tempVIP.Opportunity__c, tempVIP);
  }
 
  system.debug('VIP Count ' + vipMap.size());
}

for (Opportunity tempOpp : trigger.new)
{
  // If it's a manual update, don't touch to the stage.
  if(trigger.isUpdate)
  {
   Opportunity oldOpp = trigger.oldMap.get(tempOpp.Id);
   if (tempOpp.StageName != oldOpp.StageName)
   {
    system.debug('Opportunity Auto Stage Skipped -> Manual Stage');
    continue;
   }
  }
 
 
  // If a closing details have been created -> Min Stage = Underwriting
  if(tempOpp.StageName == null || tempOpp.StageName.toLowerCase().indexof('closed') != -1)
  {
   system.debug('Opportunity Auto Stage Skipped -> Stage Closed or Null');
   continue;
  }
  if (closingMap.containsKey(tempOpp.Id))
  {
   Closing_Detail__c c = closingMap.get(tempOpp.Id);
   if (c.Bank_Approval__c)
    tempOpp.StageName = 'Closed – Win';
   else if(c.Bank_Refusal__c)
   {
    tempOpp.StageName = 'Closed - Lost';
    tempOpp.Lost_Reason__c = 'Bank Refusal';
   }
   else
    tempOpp.StageName = 'Underwriting';
  }
  // Then check if there is a remaining question
  else if (tempOpp.Question_Counter__c > 0)  
  {
   tempOpp.StageName = 'Question to Answer';
  }
  else
  {
   if (tempOpp.VIP__c != null)
   {
    VIP__c tempVIP = vipMap.get(tempOpp.Id);
    system.debug('Found VIP');
    if(tempVip != null)
    {
     if (tempVip.Canceled__c != null)
     {
      if (tempVip.Canceled__c == true)
      {
       tempOpp.StageName = 'Closed-Lost';
       tempOpp.Lost_Reason__c = 'VIP Canceled';
      }
     }
    }
    else
    {
     tempOpp.StageName = 'VIP';
    }
    
   }
   else if (tempOpp.Walking_Attemps_Counter__c >= 3)
   {
    tempOpp.StageName = '3+ Visits Sales Office';
   }
   else if (tempOpp.Walking_Attemps_Counter__c >= 2)
   {
    tempOpp.StageName = '2 Visits Sales Office';
   }
   else if (tempOpp.Walking_Attemps_Counter__c >= 1)
   {
    tempOpp.StageName = '1 Visit Sales Office';
   }
   else if (tempOpp.Call_Attemps_Counter__c >= 3)
   {
    tempOpp.StageName = '3+ Calls Made';
   }
   else if (tempOpp.Call_Attemps_Counter__c >= 2)
   {
    tempOpp.StageName = '2 Calls Made';
   }
   else if (tempOpp.Call_Attemps_Counter__c >= 1)
   {
    tempOpp.StageName = '1 Call Made';
   }
   else
   {
    tempOpp.StageName = '0 Call Made';
   }
  }
}
 
return;
Best Answer chosen by Gab Silvermotion
Gab SilvermotionGab Silvermotion
i just found out that the source instance is in english and the target instance was setup in a different language (french), i'll translate the ''type'' picklist and try again. 

All Answers

kevin Carotherskevin Carothers
I set up your trigger in my dev org (without the code or the Closing_Detail__c object) and it seems to run through line #52 fine...    

User-added image


It's a little curious to me that in your if statement you specifically test for the Type = 'Question'  but then in the if statement you test for "startsWith('call')".

Is there anything different in the setup of the opportunity or Task object between your instances?
Also, does your test class cover this line of code?

Gab SilvermotionGab Silvermotion
i just found out that the source instance is in english and the target instance was setup in a different language (french), i'll translate the ''type'' picklist and try again. 
This was selected as the best answer