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
fdacruzfdacruz 

Apex Trigger on OpportunityLineItem: Attempt to de-reference a null object error

I've been trying to figure this error out for a while now and it seems that I just can't figure it out. When adding an opportunitylineitem to an opportunity, I keep receiving the "Attempt to de-reference a null object" error right after the `prod.inventory_forecast__c += (oli.quantity * opps.get(oli.OpportunityId).probability);` line
trigger InventoryForecast on OpportunityLineItem (after update, after insert) {
    
    Product2[] prods;
    Product2 prod;
    
    // creates a map of opportunities
    Set<ID> oppIds = new Set<ID>();
    for(OpportunityLineItem oli : Trigger.new) {oppIds.add(oli.opportunityId);}
    Map<ID, Opportunity> opps = new Map<ID, Opportunity>([SELECT Id, Probability FROM Opportunity WHERE Id IN :oppIds]);
    
    
    // creates a map of products
    Set<ID> prodIds = new Set<ID>();
    for(OpportunityLineItem oli : Trigger.new) {prodIds.add(oli.Product2Id);}
    System.debug(prodIds);
    Map<ID, Product2> prods2 = new Map<ID, Product2>([SELECT Id, inventory_forecast__c FROM Product2 WHERE Id IN :prodIds]);
    
    
    OpportunityLineItem oldOLI, newOLI;
    Decimal diff;
    
    for(OpportunityLineItem oli : Trigger.New){
        
        if(Trigger.isInsert){
            // increase forecast by amount * opp probability
            
            prod = prods2.get(oli.Product2Id);
            System.debug(prod);
            prod.inventory_forecast__c += (oli.quantity * opps.get(oli.OpportunityId).probability);
            
            prods.add(prod);
            
        }
        /*
        if(Trigger.isUpdate){
            // increase of decrease forecast by amount
            // compare Trigger.New to Trigger.Old
        
            // use newMap and oldMap as lists may not have same records and records may not be in same order
            oldOLI = Trigger.oldMap.get(oli.Id);
            newOLI = Trigger.newMap.get(oli.Id);
            
            if(newOLI.quantity == null) {newOLI.quantity = 0;}
            if(oldOLI.quantity == null) {oldOLI.quantity = 0;}
            
            diff = (newOLI.quantity - oldOLI.quantity) * opps.get(oli.OpportunityId).probability;
            
            
            prod = prods2.get(oli.Product2Id);
            prod.inventory_forecast__c += diff;
            
            prods.add(prod);
            
        }
        */
    }
    
    update prods;

}

 
Best Answer chosen by fdacruz
rajat Maheshwari 6rajat Maheshwari 6

Hi Felipe,

Please use this code in simple and optimized manner, Hope it will helps :)

trigger InventoryForecast on OpportunityLineItem (after update, after insert) {
    
    Product2[] prods;
    Product2 prod;
    
    // creates a map of opportunities
    Set<ID> oppIds = new Set<ID>();
     Set<ID> prodIds = new Set<ID>();
    for(OpportunityLineItem oli : Trigger.new)
 {
      oppIds.add(oli.opportunityId);
      prodIds.add(oli.Product2Id);
 }

    Map<ID, Opportunity> opps = new Map<ID, Opportunity>([SELECT Id, Probability FROM Opportunity WHERE Id IN :oppIds]);
    
   Map<ID, Product2> prods2 = new Map<ID, Product2>([SELECT Id, inventory_forecast__c FROM Product2 WHERE Id IN :prodIds]);
    
    
    OpportunityLineItem oldOLI, newOLI;
    Decimal diff;
    
    for(OpportunityLineItem oli : Trigger.New){
        
        if(Trigger.isInsert){
            // increase forecast by amount * opp probability
                  if(prods2!=null && prods2.containsKey(oli.Product2Id) && opps!=null && opps.containsKey(oli.OpportunityId))
              {
    
            prods2.get(oli.Product2Id).inventory_forecast__c += (oli.quantity * opps.get(oli.OpportunityId).probability);
            
         
            
        }
}
}
        /*
        if(Trigger.isUpdate){
            // increase of decrease forecast by amount
            // compare Trigger.New to Trigger.Old
        
            // use newMap and oldMap as lists may not have same records and records may not be in same order
            oldOLI = Trigger.oldMap.get(oli.Id);
            newOLI = Trigger.newMap.get(oli.Id);
            
            if(newOLI.quantity == null) {newOLI.quantity = 0;}
            if(oldOLI.quantity == null) {oldOLI.quantity = 0;}
            
            diff = (newOLI.quantity - oldOLI.quantity) * opps.get(oli.OpportunityId).probability;
            
            
            prod = prods2.get(oli.Product2Id);
            prod.inventory_forecast__c += diff;
            
            prods.add(prod);
            
        }
        */
    
    
   if(prods!=null && prods.values()!=null)
        update prods.values();

}

Please let me know, the results

Thanks
Rajat Maheshwari
rajatzmaheshwari@gmail.com

All Answers

NagendraNagendra (Salesforce Developers) 
Hi Felipe,

Your issue is most likely due to prod.inventory_forecast__c being null.

Change it to this:
if(prod.inventory_forecast__c == null) prod.inventory_forecast__c = 0; if(oli.quantity == null || opps.get(oli.OpportunityId).probability == null) prod.inventory_forecast__c = 0; else prod.inventory_forecast__c += ( (oli.quantity == null ? 0 : oli.quantity) * opps.get(oli.OpportunityId).probability);
The first if may be overkill but just in case.

Checking the maps may be overkill since an OLI cannot exist without the OpportunityId being populated. As long as you construct the prior code properly the maps should be safe to simply get and dereference.

Whenever you dereference
+=, -=
.[field]
[string].startsWith() and other string methods
etc

You need to ensure that the value being dereferenced is not null.

Hope this helps.

Please mark this as solved so that it gets removed from the unanswered queue which results in helping others who are encountering a similar issue.

Regards,
Nagendra.
rajat Maheshwari 6rajat Maheshwari 6

Hi Felipe,

Please use this code in simple and optimized manner, Hope it will helps :)

trigger InventoryForecast on OpportunityLineItem (after update, after insert) {
    
    Product2[] prods;
    Product2 prod;
    
    // creates a map of opportunities
    Set<ID> oppIds = new Set<ID>();
     Set<ID> prodIds = new Set<ID>();
    for(OpportunityLineItem oli : Trigger.new)
 {
      oppIds.add(oli.opportunityId);
      prodIds.add(oli.Product2Id);
 }

    Map<ID, Opportunity> opps = new Map<ID, Opportunity>([SELECT Id, Probability FROM Opportunity WHERE Id IN :oppIds]);
    
   Map<ID, Product2> prods2 = new Map<ID, Product2>([SELECT Id, inventory_forecast__c FROM Product2 WHERE Id IN :prodIds]);
    
    
    OpportunityLineItem oldOLI, newOLI;
    Decimal diff;
    
    for(OpportunityLineItem oli : Trigger.New){
        
        if(Trigger.isInsert){
            // increase forecast by amount * opp probability
                  if(prods2!=null && prods2.containsKey(oli.Product2Id) && opps!=null && opps.containsKey(oli.OpportunityId))
              {
    
            prods2.get(oli.Product2Id).inventory_forecast__c += (oli.quantity * opps.get(oli.OpportunityId).probability);
            
         
            
        }
}
}
        /*
        if(Trigger.isUpdate){
            // increase of decrease forecast by amount
            // compare Trigger.New to Trigger.Old
        
            // use newMap and oldMap as lists may not have same records and records may not be in same order
            oldOLI = Trigger.oldMap.get(oli.Id);
            newOLI = Trigger.newMap.get(oli.Id);
            
            if(newOLI.quantity == null) {newOLI.quantity = 0;}
            if(oldOLI.quantity == null) {oldOLI.quantity = 0;}
            
            diff = (newOLI.quantity - oldOLI.quantity) * opps.get(oli.OpportunityId).probability;
            
            
            prod = prods2.get(oli.Product2Id);
            prod.inventory_forecast__c += diff;
            
            prods.add(prod);
            
        }
        */
    
    
   if(prods!=null && prods.values()!=null)
        update prods.values();

}

Please let me know, the results

Thanks
Rajat Maheshwari
rajatzmaheshwari@gmail.com
This was selected as the best answer
rajat Maheshwari 6rajat Maheshwari 6
Hi Felipe,

Did you get a chance to look over the code ?

Please let me know in case of any help/query 


Thanks
Rajat Maheshwari
rajatzmaheshwari@gmail.com
 
fdacruzfdacruz
Hi Rajat - thanks for the help and optimization!

Upon further debugging, the cause of the null error, I discovered today, was that the "Inventory_Forecast__c" field was blank.
rajat Maheshwari 6rajat Maheshwari 6
Does your issue get solved ? Please mark as best answer, If it works :) otherwise let me know the issue 

Thanks
Rajat Maheshwari
rajatzmaheshwari@gmail.com