You need to sign in to do that
Don't have an account?

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);
}
}
Regardless, instead of using List<Contact> contactsToUpdate, you should instead choose to use a Map, like so:
Then, add the contact to the map:
Then, when you update:
It is up to you to decide what should happen if one contact has multiple values that could be assigned.
All Answers
Did you try adding a debug statement before the statment to display the Contacts and see what the contacts list have?
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:
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:
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:
Finally, you can write your loop as:
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).
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;
}
}
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;
}
}
My apologies. The original line 37, I made a typo:
Try that and let me know what you get.
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: []
"
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).
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.
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?
Regardless, instead of using List<Contact> contactsToUpdate, you should instead choose to use a Map, like so:
Then, add the contact to the map:
Then, when you update:
It is up to you to decide what should happen if one contact has multiple values that could be assigned.
After making these changes I am no longer receiving and error.
Thanks!