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
lawlaw 

System.ListException: List index out of bounds: 2

Hello All I am receiving the following error: System.ListException: List index out of bounds: 2  Trigger.UpdateFieldsFromLogMeeting: line 37, column 1: []

 

The value of i at the time of the error is  2.   Not sure what I need to do in the loop to resolve this.

Any help would be much appreciated.   Code is below.   Line 37 is " Contact c = contacts.get(i);"

 

   for (Integer i = 0; i < Trigger.new.size(); i++) {

             Task t = Trigger.new.get(i);
             if (t.Status == 'Completed' && (t.Type == 'Face-to-Face Meeting' || t.Type == 'Follow Up') &&
                t.RecordTypeId != callRecId){
                   //Select the contact associated with t he new Meeting
                   system.debug ('VALUE OF I = ' + i);
                   Contact c = contacts.get(i);
                   
              
                   c.Viability__c = t.Viability__c;
                   c.Estimated_T_12__c=t.Estimated_T_12__c;
                   c.Estimated_AUM__c=t.Estimated_AUM__c;
                   
                   String roleName = '';
                   if ( users.containsKey(t.Ownerid) ) {
                        User u = users.get(t.Ownerid);
                        System.Debug('User ' + u.Name);
                        roleName = u.UserRole.Name.toLowerCase();
                        System.Debug('ROLE ' + roleName);                   
                   } else {
                        System.Debug('Owner Not Found');
                   }
                   
                   
                    if ( roleName.contains ('regional dir-ear')) {
                       System.Debug('Role Name = ' + roleName);
                        if (c.EAR_Assist__c == false || c.EAR_Assist_Name__c == null || c.EARAssistTask__c == t.id  ) {
                            
                            c.EAR_Assist__c = true;
                            c.EAR_Assist_Name__c = t.Ownerid;
                            c.EARAssistTask__c = t.id;
                            
                            if ( c.LeadSource == 'Self-Sourced') {
                                c.EAR_Validate__c = true;
                                c.EAR_Validation_Date__c = t.ActivityDate;
                            }                               
                        } else if ( c.EAR_Assist_Name__c == t.Ownerid ) {
                            c.EAR_Validate__c = true;                           
                            if (c.EAR_Validation_Date__c == null || t.ActivityDate > c.EAR_Validation_Date__c) {                            
                                c.EAR_Validation_Date__c = t.ActivityDate;
                            }                                                           
                        }   
                    
                   }
                                      
                  contactsToUpdate.add(c);

             }

         }

Best Answer chosen by Admin (Salesforce Developers) 
sfdcfoxsfdcfox

Regardless, instead of using List<Contact> contactsToUpdate, you should instead choose to use a Map, like so:

 

map<id,contact> contactstoupdate = new map<id,contact>():

Then, add the contact to the map:

 

contactstoupdate.put(c.id,c);

Then, when you update:

 

update contactstoupdate.values();

It is up to you to decide what should happen if one contact has multiple values that could be assigned. 

All Answers

Naidu PothiniNaidu Pothini

Did you try adding a debug statement before the statment to display the Contacts and see what the contacts list have?

sfdcfoxsfdcfox

I presume that you probably queried a list of contacts based on the whoid earlier in the code?

 

If so, it appears you made two false assumptions: (1) that the list would be queried in the same order as the list of whoids provided, and (2) that each instance of a contact would be duplicated in the query.

 

The first part of your code should read:

 

trigger ... on task(...) {
  map<id,contact> contacts = new map<id,contact>();
  for(task record:trigger.new) {
    if(record.whoid!=null&&record.whoid.getsobjecttype()==contact.sobjecttype) {
      contacts.put(record.whoid,null);
    }
  }
  contacts.putall([select ... from contact where id in :contacts.keyset()]);

You just need to fill in the "...".

 

Now, back on line 37 (which might move, so keep track of it), you need to determine which contact you'll use:

 

Contact c = contacts.get(task.whoid);

Now, you've made one other small problem: you also assume that the contact will be available. But tasks can also be assigned to leads, or they might not have any whoid value at all (unless you put validation in place). So, you should consider skipping that task if no contact was found:

 

if(c==null) {
  continue;
}

Finally, you can write your loop as:

 

for(task t:trigger.new) {

Which is more efficient in terms of heap size and number of script statements (and, in my opinion, makes you look cooler for knowing when to use a for-each loop instead of a for loop).

lawlaw

Thanks SFDCfox

 

However I did not query on WhoID.  The complete trigger is below:

____________________________

trigger UpdateFieldsFromLogMeeting on Task (after insert, after update) {
SingletonResource singleton = SingletonResource.getInstance();

Id callRecId = singleton.callRecId;
Id meetingRecId = singleton.meetingRecId;
Id faceRecId = singleton.faceToFaceRecId;
Id prospectRecId = singleton.prospectRecId;
Id candidateRecId = singleton.candidateRecId;

list<Id> ContactIds = new List<Id>();
list<Id> OwnerIds = new List<Id>();

System.Debug('Go through tasks');
for(task t : Trigger.new) {
ContactIds.add(t.WhoId);
System.Debug('Task Owner: ' + t.OwnerId);
OwnerIds.add(t.OwnerId);
}

list<Contact> contacts = [SELECT Id,Phone,FirstName,Email, EAR_Assist__c, EAR_Assist_Name__c, EAR_Validate__c, EAR_Validation_Date__c, LeadSource, EARAssistTask__c FROM Contact WHERE Id in :ContactIds];
list<Contact> contactsToUpdate = new list<Contact>();

Map<Id,User> users = new Map<Id,User>();

for(User u : [Select id, Name, UserRole.Name from User u where u.id in :OwnerIds]) {
System.Debug('UserRole.Name loop:' + u.userrole.name);
users.put(u.id, u);
}

for (Integer i = 0; i < Trigger.new.size(); i++) {

Task t = Trigger.new.get(i);
if (t.Status == 'Completed' && (t.Type == 'Face-to-Face Meeting' || t.Type == 'Follow Up') &&
t.RecordTypeId != callRecId){
//Select the contact associated with t he new Meeting
system.debug ('VALUE OF I = ' + i);
Contact c = contacts.get(i);


c.Viability__c = t.Viability__c;
c.Estimated_T_12__c=t.Estimated_T_12__c;
c.Estimated_AUM__c=t.Estimated_AUM__c;

String roleName = '';
if ( users.containsKey(t.Ownerid) ) {
User u = users.get(t.Ownerid);
System.Debug('User ' + u.Name);
roleName = u.UserRole.Name.toLowerCase();
System.Debug('ROLE ' + roleName);
} else {
System.Debug('Owner Not Found');
}


if ( roleName.contains ('regional dir-ear')) {
System.Debug('Role Name = ' + roleName);
if (c.EAR_Assist__c == false || c.EAR_Assist_Name__c == null || c.EARAssistTask__c == t.id ) {

c.EAR_Assist__c = true;
c.EAR_Assist_Name__c = t.Ownerid;
c.EARAssistTask__c = t.id;

if ( c.LeadSource == 'Self-Sourced') {
c.EAR_Validate__c = true;
c.EAR_Validation_Date__c = t.ActivityDate;
}
} else if ( c.EAR_Assist_Name__c == t.Ownerid ) {
c.EAR_Validate__c = true;
if (c.EAR_Validation_Date__c == null || t.ActivityDate > c.EAR_Validation_Date__c) {
c.EAR_Validation_Date__c = t.ActivityDate;
}
}

}

contactsToUpdate.add(c);

}

}

if ( contactsToUpdate.size() != 0) {
update contactsToUpdate;
}
}

lawlaw

I have made the modifications you indicated and I am now receiving the following error: "

Description Resource Path Location Type
Save error: Incompatible key type Schema.SObjectField for MAP<Id,Contact> UpdateFieldsFromLogMeeting.trigger EAR TEST E2/src/triggers line 49 Force.com save problem

"

 

Complete Modified trigger is below.

 

______________________________________

 

trigger UpdateFieldsFromLogMeeting on Task (after insert, after update) {
SingletonResource singleton = SingletonResource.getInstance();

Id callRecId = singleton.callRecId;
Id meetingRecId = singleton.meetingRecId;
Id faceRecId = singleton.faceToFaceRecId;
Id prospectRecId = singleton.prospectRecId;
Id candidateRecId = singleton.candidateRecId;

list<Id> ContactIds = new List<Id>();
list<Id> OwnerIds = new List<Id>();

System.Debug('Go through tasks');
// for(task t : Trigger.new) {
// ContactIds.add(t.WhoId);
// System.Debug('Task Owner: ' + t.OwnerId);
// OwnerIds.add(t.OwnerId);
// }

//------------------------------------------------
map<id,contact> contacts = new map<id,contact>();
for(task record:trigger.new) {
if(record.whoid!=null&&record.whoid.getsobjecttype()==contact.sobjecttype) {
contacts.put(record.whoid,null);
}
}
contacts.putall([select Id,Phone,FirstName,Email, EAR_Assist__c, EAR_Assist_Name__c, EAR_Validate__c, EAR_Validation_Date__c, LeadSource, EARAssistTask__c from contact where id in :contacts.keyset()]);
//------------------------------------------------

list<Contact> contactsToUpdate = new list<Contact>();

Map<Id,User> users = new Map<Id,User>();

for(User u : [Select id, Name, UserRole.Name from User u where u.id in :OwnerIds]) {
System.Debug('UserRole.Name loop:' + u.userrole.name);
users.put(u.id, u);
}

for(task t:trigger.new) {

if (t.Status == 'Completed' && (t.Type == 'Face-to-Face Meeting' || t.Type == 'Follow Up') &&
t.RecordTypeId != callRecId){
//Select the contact associated with t he new Meeting

Contact c = contacts.get(task.whoid);

if(c==null) {
continue;
}

 

 

c.Viability__c = t.Viability__c;
c.Estimated_T_12__c=t.Estimated_T_12__c;
c.Estimated_AUM__c=t.Estimated_AUM__c;

String roleName = '';
if ( users.containsKey(t.Ownerid) ) {
User u = users.get(t.Ownerid);
System.Debug('User ' + u.Name);
roleName = u.UserRole.Name.toLowerCase();
System.Debug('ROLE ' + roleName);
} else {
System.Debug('Owner Not Found');
}


if ( roleName.contains ('regional dir-ear')) {
System.Debug('Role Name = ' + roleName);
if (c.EAR_Assist__c == false || c.EAR_Assist_Name__c == null || c.EARAssistTask__c == t.id ) {

c.EAR_Assist__c = true;
c.EAR_Assist_Name__c = t.Ownerid;
c.EARAssistTask__c = t.id;

if ( c.LeadSource == 'Self-Sourced') {
c.EAR_Validate__c = true;
c.EAR_Validation_Date__c = t.ActivityDate;
}
} else if ( c.EAR_Assist_Name__c == t.Ownerid ) {
c.EAR_Validate__c = true;
if (c.EAR_Validation_Date__c == null || t.ActivityDate > c.EAR_Validation_Date__c) {
c.EAR_Validation_Date__c = t.ActivityDate;
}
}

}

contactsToUpdate.add(c);

}

}

if ( contactsToUpdate.size() != 0) {
update contactsToUpdate;
}
}

sfdcfoxsfdcfox

My apologies. The original line 37, I made a typo:

 

Contact c = contacts.get(t.whoid);

Try that and let me know what you get.

lawlaw

No I receive the following error when the trigger fires:

 

"

EDP1.ContactChanges: execution of AfterUpdate

caused by: System.DmlException: Update failed. First exception on row 0 with id 00TJ000000HijEzMAJ; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, UpdateFieldsFromLogMeeting: execution of AfterUpdate

caused by: System.ListException: Duplicate id in list: 003U0000007QoQWIA0

Trigger.UpdateFieldsFromLogMeeting: line 100, column 1: []

"

Naidu PothiniNaidu Pothini
trigger UpdateFieldsFromLogMeeting on Task (after insert, after update) 
{
	SingletonResource singleton = SingletonResource.getInstance();

	Id callRecId = singleton.callRecId;
	Id meetingRecId = singleton.meetingRecId;
	Id faceRecId = singleton.faceToFaceRecId;
	Id prospectRecId = singleton.prospectRecId;
	Id candidateRecId = singleton.candidateRecId;

	list<Id> ContactIds = new List<Id>();
	list<Id> OwnerIds = new List<Id>();
	System.Debug('Go through tasks');
	// for(task t : Trigger.new) {
	// ContactIds.add(t.WhoId);
	// System.Debug('Task Owner: ' + t.OwnerId);
	// OwnerIds.add(t.OwnerId);
	// }

	//------------------------------------------------
	map<id,contact> contacts = new map<id,contact>(); 

	for(task record:trigger.new)
	{
		if(record.whoid != null && record.whoid.getsobjecttype() == Contact.sobjecttype)
		{
			contacts.put(record.whoid,null);
		}
	}
	
	contacts.putall([SELECT Id, Phone, FirstName, Email, EAR_Assist__c, EAR_Assist_Name__c, EAR_Validate__c, EAR_Validation_Date__c, LeadSource, EARAssistTask__c FROM Contact WHERE Id IN :contacts.keyset()]);
	//------------------------------------------------

	list<Contact> contactsToUpdate = new list<Contact>();

	Map<Id,User> users = new Map<Id,User>();

	for(User u : [SELECT Id, Name, UserRole.Name FROM User WHERE Id IN :OwnerIds])
	{
		System.Debug('UserRole.Name loop:' + u.userrole.name);
		users.put(u.id, u);
	}

	for(task t:trigger.new)
	{
		if (t.Status == 'Completed' && (t.Type == 'Face-to-Face Meeting' || t.Type == 'Follow Up') && t.RecordTypeId != callRecId)
		{
			//SELECT the contact associated with t he new Meeting
			Contact c = contacts.get(t.whoid);

			if(c==null)
			{
				continue;
			}
	 	 
			c.Viability__c = t.Viability__c;
			c.Estimated_T_12__c=t.Estimated_T_12__c;
			c.Estimated_AUM__c=t.Estimated_AUM__c;
			String roleName = '';

			if ( users.containsKey(t.Ownerid) )
			{
				User u = users.get(t.Ownerid);
				System.Debug('User ' + u.Name);
				roleName = u.UserRole.Name.toLowerCase();
				System.Debug('ROLE ' + roleName);
			}
			else
			{
				System.Debug('Owner Not Found');
			}
			
			if ( roleName.contains ('regional dir-ear'))
			{
				System.Debug('Role Name = ' + roleName);
				if (c.EAR_Assist__c == false || c.EAR_Assist_Name__c == null || c.EARAssistTask__c == t.id )
				{
					c.EAR_Assist__c = true;
					c.EAR_Assist_Name__c = t.Ownerid;
					c.EARAssistTask__c = t.id;

					if ( c.LeadSource == 'Self-Sourced')
					{
						c.EAR_Validate__c = true;
						c.EAR_Validation_Date__c = t.ActivityDate;
					}
				}
				else if ( c.EAR_Assist_Name__c == t.Ownerid )
				{
					c.EAR_Validate__c = true;
					if (c.EAR_Validation_Date__c == null || t.ActivityDate > c.EAR_Validation_Date__c)
					{
						c.EAR_Validation_Date__c = t.ActivityDate;
					}
				}
			}
			contactsToUpdate.add(c);
		}
	}

	if ( contactsToUpdate.size() != 0)
	{
		update contactsToUpdate;
	}
}

 how many tasks were you updating/inserting?

if you  are inserting/updating more than one task for the same contact, then the contact is being added to ContactsToUpdate List more than once (duplicate contact in the same list).

lawlaw

On there contact that produces this error, there are 7 completed tasks and 1 open task.   I am reassigning the owner of this contact which in turn causes the  task trigger to fire for all tasks associated with this contact.

Naidu PothiniNaidu Pothini

So if you add a debug statement before the update. you can see the list will have the same contact 7 times.

 

What if a contact has two tasks which satisfies all the conditions, which task values should the contact be updated with?

sfdcfoxsfdcfox

Regardless, instead of using List<Contact> contactsToUpdate, you should instead choose to use a Map, like so:

 

map<id,contact> contactstoupdate = new map<id,contact>():

Then, add the contact to the map:

 

contactstoupdate.put(c.id,c);

Then, when you update:

 

update contactstoupdate.values();

It is up to you to decide what should happen if one contact has multiple values that could be assigned. 

This was selected as the best answer
lawlaw

After making these changes I am no longer receiving and error.

 

Thanks!