+ Start a Discussion
ManderMander 

System.ListException: List index out of bounds:

I've been working on this trigger for days and I'm stuck.  

 

It's supposed to add the number of hours from a new budget to the hours that already exist on a project.  The first version worked, but testing was throwing Too many SOQL queries: 101 error.

 

So I tried to add the lists in and now I'm getting the following message and the trigger doesn't work.   

      System.DmlException: Insert failed. First exception on row 0; first error:      

      CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, SumChangeHours: execution of AfterInsert

      caused by: System.ListException: List index out of bounds: 0

      Trigger.SumChangeHours: line 49, column 1: []

 

Can someone help me, please?

 

Version 1

trigger SumChangeHours on pse__Budget__c (after insert, after update ,after delete) {
List<pse__Proj__c> listProjToUpdate = new List<pse__Proj__c>();
    Set<ID> setProjIds = new Set<ID>();
    List<Database.SaveResult> dmlResults;
    
if(trigger.isInsert || trigger.isUpdate){
        for(pse__Budget__c B : trigger.new){
            if(B.pse__Project__c != null) {
                setProjIds.add(B.pse__Project__c);
            }
        }
    }    

    if(trigger.isDelete){ 
        for(pse__Budget__c B : trigger.old){  
            if(B.pse__Project__c != null ){ 
                setProjIds.add(B.pse__Project__c);            
            }
        }
    }
    
System.debug('##########setProjIds:'+setProjIds);

   for(pse__Proj__c proj : [Select Id, Total_Installation_Hours_Sold__c, Total_CAD_Hours_Sold__c, Total_Commissioning_Hours_Sold__c, Total_Network_Engineer_Hours_Sold__c, Total_Programming_Hours_Sold__c, Total_Pro_Services_Hours_Sold__c, 
       (Select Id, pse__Project__c, CAD_Hours__c, Commissioning_Hours__c, Installation_Hours__c, Network_Engineer_Hours__c, Programming_Hours__c, Pro_Services_Hours__c From pse__Budgets__r) 
       From pse__Proj__c Where Id IN :setProjIds]){       

    proj.Total_CAD_Hours_Sold__c=0;
    proj.Total_Commissioning_Hours_Sold__c=0;
    proj.Total_Installation_Hours_Sold__c=0;
    proj.Total_Network_Engineer_Hours_Sold__c=0;
    proj.Total_Programming_Hours_Sold__c=0;
    proj.Total_Pro_Services_Hours_Sold__c=0;


    for(pse__Budget__c B : proj.pse__Budgets__r){

        if( B.CAD_Hours__c != null){
            proj.Total_CAD_Hours_Sold__c+= B.CAD_Hours__c;}
        
        if(B.Pro_Services_Hours__c != null){
            proj.Total_Pro_Services_Hours_Sold__c += B.Pro_Services_Hours__c;}

        if(B.Programming_Hours__c!= null){
             proj.Total_Programming_Hours_Sold__c += B.Programming_Hours__c;}
            
        if(B.Installation_Hours__c != null){
            proj.Total_Installation_Hours_Sold__c += B.Installation_Hours__c;}

        if(B.Network_Engineer_Hours__c != null){
            proj.Total_Network_Engineer_Hours_Sold__c += B.Network_Engineer_Hours__c;}    

      }
      listProjToUpdate.add(proj);
    }


//Update Project Records
  dmlResults = Database.update(listProjToUpdate,false);
  //Process the Update results.
  addErrorMsgs(dmlResults);
  
  public void addErrorMsgs(List<Database.SaveResult> results){
    for(Database.SaveResult result : results){
      if( !result.isSuccess() ){
        
        for(Database.Error DbError : result.getErrors()){
          // Check if the error is related to trival access level.
          // Access levels equal or more permissive than the object's default
          // access level are not allowed.
          // These sharing records are not required and thus an insert exception is acceptable.
          if(DbError.getStatusCode() == StatusCode.FIELD_INTEGRITY_EXCEPTION &&
          DbError.getMessage().contains('AccessLevel')){
          // Indicates success.
            continue;
          }else{
            System.debug('##Error:'+DbError.getMessage());
            
            if(trigger.isInsert || trigger.isUpdate)
              trigger.new[0].addError(DbError.getMessage());
            
            if(trigger.isDelete)
              trigger.old[0].addError(DbError.getMessage());
          }
        }
      }
    }
  }

}

 Version 2

trigger SumChangeHours on pse__Budget__c (after insert, after update ,after delete) {

List<pse__Proj__c> listProjToUpdate = new List<pse__Proj__c>();

    //set of ids for triggered budgets
    set<ID> setBudgetIds= new set<ID>();
    
    // set of project ids for triggered transaction line items. 
    set<ID> setProjectIds=new set<ID>(); 

    //Map from Project.Id to Project object
    map<ID,pse__Proj__c> mapProjIdToProject = new map<ID,pse__Proj__c>();

    //temp project for updating
    pse__Proj__c oTmpProject;

List<Database.SaveResult> dmlResults;

    //when budget is added or updated
    if(trigger.isInsert|| trigger.isUpdate){

        //adding budget ids from trigger.new
        for(pse__Budget__c OB : Trigger.new){
            setBudgetIds.add(OB.id);
            }
        }

    //when budget is deleted
    if(trigger.isDelete){
        //adding budget ids from trigger.old
        for(pse__Budget__c OB : Trigger.old){
            setBudgetIds.add(OB.id);
            }
        }

    //making map of projects for updating
    List<pse__Proj__c> proj = [Select Id, Total_Installation_Hours_Sold__c, Total_CAD_Hours_Sold__c, Total_Commissioning_Hours_Sold__c, Total_Network_Engineer_Hours_Sold__c, Total_Programming_Hours_Sold__c, Total_Pro_Services_Hours_Sold__c, 
       (Select Id, pse__Project__c, CAD_Hours__c, Commissioning_Hours__c, Installation_Hours__c, Network_Engineer_Hours__c, Programming_Hours__c, Pro_Services_Hours__c From pse__Budgets__r) 
       From pse__Proj__c Where Id IN :setProjectIds];{   

    //clearing out the older values for project's specific fields
    proj[0].Total_CAD_Hours_Sold__c=0;
    proj[0].Total_Commissioning_Hours_Sold__c=0;
    proj[0].Total_Installation_Hours_Sold__c=0;
    proj[0].Total_Network_Engineer_Hours_Sold__c=0;
    proj[0].Total_Programming_Hours_Sold__c=0;
    proj[0].Total_Pro_Services_Hours_Sold__c=0;
    
    //adding to map projects
    mapProjIdToProject.put(proj[0].Id, Proj[0]);
    
    //Making set of all related budget ids.
    for(pse__Budget__c OBH : Proj[0].pse__Budgets__r){
        setBudgetIds.add(OBH.id);
        }

    //updates project's fields to new value
    oTmpProject = mapProjIdToProject.get(proj[0].id);
    for(pse__Budget__c OB : proj[0].pse__Budgets__r){

        if(OB.CAD_Hours__c != null){
            oTmpProject.Total_CAD_Hours_Sold__c+= OB.CAD_Hours__c;}
        
        if(OB.Pro_Services_Hours__c != null){
            oTmpProject.Total_Pro_Services_Hours_Sold__c += OB.Pro_Services_Hours__c;}

        if(OB.Programming_Hours__c!= null){
             oTmpProject.Total_Programming_Hours_Sold__c += OB.Programming_Hours__c;}
            
        if(OB.Installation_Hours__c != null){
            oTmpProject.Total_Installation_Hours_Sold__c += OB.Installation_Hours__c;}

        if(OB.Network_Engineer_Hours__c != null){
            oTmpProject.Total_Network_Engineer_Hours_Sold__c += OB.Network_Engineer_Hours__c;} 

        }
        }

    //Update Project Records
    dmlResults = Database.update(mapProjIdToProject.values(),false);
    //Process the Update results.
    addErrorMsgs(dmlResults);

public void addErrorMsgs(List<Database.SaveResult> results){
    for(Database.SaveResult result : results){
      if( !result.isSuccess() ){
        
        for(Database.Error DbError : result.getErrors()){
          // Check if the error is related to trival access level.
          // Access levels equal or more permissive than the object's default
          // access level are not allowed.
          // These sharing records are not required and thus an insert exception is acceptable.
          if(DbError.getStatusCode() == StatusCode.FIELD_INTEGRITY_EXCEPTION &&
          DbError.getMessage().contains('AccessLevel')){
          // Indicates success.
            continue;
          }else{
            System.debug('##Error:'+DbError.getMessage());
            
            if(trigger.isInsert || trigger.isUpdate)
              trigger.new[0].addError(DbError.getMessage());
            
            if(trigger.isDelete)
              trigger.old[0].addError(DbError.getMessage());  
          }
        }
      }
    }
  }

  
}

 Thanks!

Vinita_SFDCVinita_SFDC

Hello Mander,

 

Always before accessing the list, you must check for whether list is empty.

 

Consider the following Example:

List lstAccount = [Select Id, Name from Account Limit 10];
 
// Before processing the list check if its empty or not
// It will go inside the loop only if the List is having values in it.
 
if(lstAccount.size() > 0) {
    // Do something with lstAccount[0].Name
}
 
// If you try to access lstAccount[0] without empty check then it will obviously throw that error!!

 

Before refering to the 0th index of list you must perform a check on whether the list is empty or not. Whenever you try to access records from list first check if its empty or not.

 

Hope this helps!

UVUV

First check whether list if empty or not and then proceed-

if(!proj.isEmpty()){

//your logic 

}

ManderMander

I don't have any real training in Apex Triggers.  I've tried adding the logic that checks to see if the list is empty in a few different spots and I guess I don't know where to put that.  Where should that go?