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
Stephanie ArceStephanie Arce 

Trigger: After Update Null Pointer Exception

Can someone help me figure out what's wrong with this trigger? I'm writing it to create lookup rollup-summary esque fields on the parent object, Invoice__c, from the child Line_Item__c. I get this error though upon updating a record:

"Line_Item_Invoice_RollupTrigger: execution of AfterUpdate
caused by: System.NullPointerException: Argument cannot be null.
Trigger.Line_Item_Invoice_RollupTrigger: line 55, column 1"

Here's the trigger:
trigger Line_Item_Invoice_RollupTrigger on Line_Item__c (after update, after insert, after delete) {
     Map<Id, Double> LineItemTotal = new Map<Id, Double>();
     Map<Id, Double> LineItemTotalAdjusted = new Map<Id, Double>();
     Map<Id, Double> NumberofLineItems = new Map<Id, Double>();
     List<Invoice__c> invoicesToUpdate = new List<Invoice__c>();
     List<Line_Item__c> itemsForInvoice;
     List<Line_Item__c> items;
     if (trigger.isDelete) {
         items = trigger.old;
     }
     else {
         items = trigger.new;
    }
    // Go through all line items that the trigger is acting on.
    Set<ID> setInvoiceId = new Set<ID>();
    for (Line_Item__c triggerItem: items) {       
        
            // Get the invoice's ID for the line item and then
            // ensure its ID exists in the line item / line item adjusted totals
            // maps and their totals default to $0.00.        
        if (!LineItemTotal.containsKey(triggerItem.Invoice__c)) {
            LineItemTotal.put(triggerItem.Invoice__c, 0.0);
        }
        if (!LineItemTotalAdjusted.containsKey(triggerItem.Invoice__c)) {
            LineItemTotalAdjusted.put(triggerItem.Invoice__c, 0.0);
        }
        if (!NumberofLineItems.containsKey(triggerItem.Invoice__c)) {
            NumberofLineItems.put(triggerItem.Invoice__c, 0);
        }
        
        if(triggerItem.Invoice__c != NULL)
            setInvoiceId.add(triggerItem.Invoice__c);
    }
    
    // Sum the total cost of the line items
    // for the current invoice (see invoice above).
    //
    // 1. Get all of the line items for the invoice.
    // 2. For each line item update the mapping for the invoice 
    //    to be (previous total + total cost).    
    List<Line_Item__c> lstInvLineItem_LineItemTotal = new List<Line_Item__c>();
    List<Line_Item__c> lstInvLineItem_LineItemTotalAdjusted = new List<Line_Item__c>();
    List<Line_Item__c> lstInvLineItem_NumberofLineItems = new List<Line_Item__c> ();
    if(setInvoiceId.size()>0){
        lstInvLineItem_LineItemTotal = [SELECT Id, Cost__c, Invoice__c FROM Line_Item__c
                WHERE Invoice__c IN :setInvoiceId];
        lstInvLineItem_LineItemTotalAdjusted = [SELECT Id, Total_Cost_incl_Adjustment__c, Invoice__c FROM Line_Item__c
                WHERE Invoice__c IN :setInvoiceId];
        lstInvLineItem_NumberofLineItems = [SELECT Id, One__c, Invoice__c FROM Line_Item__c
                WHERE Invoice__c IN :setInvoiceId];
    }
    // If the list has records, add those IDs and totals to the map.
    if(lstInvLineItem_LineItemTotal.size()>0){
        for(Line_Item__c item:lstInvLineItem_LineItemTotal){    
            LineItemTotal.put(item.Invoice__c, 
                LineItemTotal.get(item.Invoice__c) + item.Cost__c); 
        }
    }
    // If the list has records, add those IDs and totals to the map.    
    if(lstInvLineItem_LineItemTotalAdjusted.size()>0){
        for(Line_Item__c item:lstInvLineItem_LineItemTotalAdjusted){    
            LineItemTotalAdjusted.put(item.Invoice__c, 
                LineItemTotalAdjusted.get(item.Invoice__c) + item.Total_Cost_incl_Adjustment__c); 
        }
    }
    
    // If the list has records, add those IDs and totals to the map.
    if(lstInvLineItem_NumberofLineItems.size()>0) {
        for(Line_Item__c item:lstInvLineItem_NumberofLineItems) {
            NumberofLineItems.put(item.Invoice__c,
                NumberofLineItems.get(item.Invoice__c) + item.One__c);
        }
    }
    
    List<Id> invoices = new List<Id>();
    for (Id previous : LineItemTotal.keyset()) {
        invoices.add(previous);
    }
    for (Id current : LineItemTotal.keyset()) {
        if (!LineItemTotal.containsKey(current)) {
            invoices.add(current);
        }
    }
    // Get a list of all invoices where its Id is in the invoices map.
    List<Invoice__c> lstInvoices = new List<Invoice__c>();
    if(invoices.size()>0){
        lstInvoices = [SELECT Id, Line_Item_Total__c, Line_Item_Total_Adjusted__c, Number_of_Line_Items__c
             FROM Invoice__c WHERE Id IN :invoices];
    }
    // Update the map with line item and line item adjusted totals.
    if(lstInvoices.size()>0){
        for(Invoice__c invoice:lstInvoices){
            if (LineItemTotal.containsKey(invoice.id)) {
                invoice.Line_Item_Total__c = LineItemTotal.get(invoice.id);
            }
            
            if (LineItemTotalAdjusted.containsKey(invoice.id)) {
                invoice.Line_Item_Total_Adjusted__c = LineItemTotalAdjusted.get(invoice.id);
            }
            
            if (NumberofLineItems.containsKey(invoice.id)) {
                invoice.Number_of_Line_Items__c = NumberofLineItems.get(invoice.id);
            }
            
            invoicesToUpdate.add(invoice);
        }
    }
    update invoicesToUpdate;
}


sbbsbb
My guess is that there is a ID (map key) mismatch. You initialized the map with a 15-char ID whereas in line 55 you are using a 18-char ID. Just a guess and something to look into using a debug statement.
Stephanie ArceStephanie Arce
Thanks! I had it working in another SF org (we're migrating + making some changes), but just realized the data types of the fields I'm summing are different. Cost__c is a currency field now where it was a "number" before.