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
Steve ThurstonSteve Thurston 

Previously working code in Sandbox now producing 'List index out of bounds' error

Ok, this is weird.  I have a trigger that has been working happily for a few months now.  Today, I went to add some functionality to it in Sandbox, and am getting a 'List index out of bounds' error where (a) it previously worked in Sandbox, and (b) it currently works in Production.  I get this error when trying to create a new Lead.

I threw a bunch of system.debug statements around it to try and identify the problem, and blast it, I can see what line it goes wrong on, but don't know why!  Basically, I am getting a Lead ID from trigger.new and using it in a SOQL statement to retrieve the relevant fields.  This is an 'after insert' trigger where I am updating some fields.  I am successfully retrieving the list of Lead ID's from the trigger.new 'for' loop.  When I check for the size of this list outside of the for loop, it says it has a size of 1, which is correct.  I can show that ID in the debug log.

But then, when I make my SOQL query using this ID list, I get a return set of 0 size!

This makes no sense.  It has been working fine, and I can see that the list I get from trigger.new is NOT zero.  But for some reason the SOQL query doesn't return anything.

Here are the relevant codes of line and results:
-----------------------------------------------
ERROR RECEIVED:
Error: Invalid Data.
...execution of AfterInsert caused by: System.ListException: List index out of bounds: 0... (Points to the last line of code given below)

RELEVANT CODE:

List<Lead> submittedLeadList = new List<Lead>();
List<Id> theLeadID = new List<Id>();

system.debug('Entering the FOR loop to read trigger.new Lead');

for (Lead leadList : trigger.new) 
     {
        theLeadID.add(leadList.Id); 

        system.debug('Lead ID:  ' + leadList.Id);
        system.debug('Lead Name:  ' + leadList.FirstName + ' ' + leadList.LastName);
     }

system.debug('Exiting FOR loop');
system.debug('Lead ID after exiting loop:  ' + theLeadID[0]);
system.debug('Number of Leads retrieved from trigger.new:  ' + theLeadID.size());

submittedLeadList = [SELECT Id, FirstName, LastName, Company, Requested_Quote_Types__c, State, New_Lead__c FROM Lead WHERE Id IN : theLeadID LIMIT 1];

system.debug('Lead List Size:  ' + submittedLeadList.size());

system.debug('SOQL Query for submittedLeadList, for Lead:  ' + submittedLeadList[0].FirstName + ' ' + submittedLeadList[0].LastName);

DEBUG RESULTS:
USER_DEBUG|[32]|DEBUG|Entering the FOR loop to read trigger.new Lead
USER_DEBUG|[38]|DEBUG|Lead ID:  00Q63000003cPewEAE
USER_DEBUG|[39]|DEBUG|Lead Name:  Test Test1
USER_DEBUG|[42]|DEBUG|Exiting FOR loop
USER_DEBUG|[43]|DEBUG|Lead ID after exiting loop:  00Q63000003cPewEAE
USER_DEBUG|[44]|DEBUG|Number of Leads retrieved from trigger.new:  1
SOQL_EXECUTE_BEGIN|[46]|Aggregations:0|SELECT Id, FirstName, LastName, Company, Requested_Quote_Types__c, State, New_Lead__c FROM Lead WHERE Id IN :tmpVar1 LIMIT 1
SOQL_EXECUTE_END|[46]|Rows:0
USER_DEBUG|[47]|DEBUG|Lead List Size:  0
FATAL_ERROR|System.ListException: List index out of bounds: 0

This is an "after insert" trigger, so the record has to exist, and its ID has to be in trigger.new.  So how can I pass a valid ID to the SOQL statement and yet not get a result?  And how is it that this same code has worked in Sandbox before, and is currently working in Production?
Amit Chaudhary 8Amit Chaudhary 8
Is this code is executing on before insert trigger ?
May be in sandbox that code was working on update event ?
Try below code
List<Lead> submittedLeadList = new List<Lead>();
List<Id> theLeadID = new List<Id>();

system.debug('Entering the FOR loop to read trigger.new Lead');

for (Lead leadList : trigger.new) 
     {
        theLeadID.add(leadList.Id); 

        system.debug('Lead ID:  ' + leadList.Id);
        system.debug('Lead Name:  ' + leadList.FirstName + ' ' + leadList.LastName);
     }

system.debug('Exiting FOR loop');
system.debug('Lead ID after exiting loop:  ' + theLeadID[0]);
system.debug('Number of Leads retrieved from trigger.new:  ' + theLeadID.size());

submittedLeadList = [SELECT Id, FirstName, LastName, Company, Requested_Quote_Types__c, State, New_Lead__c FROM Lead WHERE Id IN : theLeadID LIMIT 1];

if(submittedLeadList.size() > 0 )
{
	system.debug('Lead List Size:  ' + submittedLeadList.size());
	system.debug('SOQL Query for submittedLeadList, for Lead:  ' + submittedLeadList[0].FirstName + ' ' + submittedLeadList[0].LastName);	
}


Let us know if this will help you
 
Steve ThurstonSteve Thurston
Hi Amit,

I can confirm that it is an "after insert" trigger in both Sandbox and Prod.

i.e. trigger leadsRoundRobin on Lead (after insert) {

Putting my system.debug entry into an 'if' statement like you showed just pushes the error to the next time I try to use the results from the query.

i.e. the error now occurs on this line:  submittedLead = submittedLeadList[0];

I can see from the debug logs that I have the Lead's ID from trigger.new when I exit the for loop.  But when I try to use that ID in my SOQL statement, it comes back with an empty result set.  That just doesn't make sense!

There is something that I don't know whether or not is relevant.  I see the 'out of bounds' error when I try to save the new Lead record.  Which means I can't save the new Lead.  The full error message is:

Apex trigger leadsRoundRobin caused an unexpected exception, contact your administrator: leadsRoundRobin: execution of AfterInsert caused by: System.ListException: List index out of bounds: 0: Trigger.leadsRoundRobin: line 53, column 1

Even though my Apex is an "after insert", I can't save the record, and no new Lead exists.  I presume this is because it has been rolled back due to the error?
rajat Maheshwari 6rajat Maheshwari 6

Steve,

I just want to ask you, when you are using limit 1 in query, then why u r returned query in list, 

Please you can use this approach : - 

Lead ld =  [SELECT Id, FirstName, LastName, Company, Requested_Quote_Types__c, State, New_Lead__c FROM Lead WHERE Id IN : theLeadID LIMIT 1];

Thanks

Steve ThurstonSteve Thurston
I return it to a list even though it has a 'LIMIT 1' just because I've had some problems with that in the past and just gotten used to doing it this way.  

Assigning it directly to a Lead object doesn't change the problem, unfortunately.   The error message is, "List has no rows for assignment to SObject" at the same line of code.

The problem is that, for some reason, I can get an ID from trigger.new, but that ID doesn't return any rows in the SOQL query.
Steve ThurstonSteve Thurston
Well, I've made progress.  Although it doesn't make any sense to me.  I had an old test Lead in the system.  I deleted it, and my new Lead saved!

I'm not out of the woods yet, though.  If I try to create another Lead, I get the same error as before.  So as long as I only need one Lead in the system, I'm fine!  The ID that I see in my debug logs is the same ID as the new Lead, not the existing Lead, which is good.  (Except that the debug log is the 18 digit ID, while the URL displays the 15 digit ID.  Not unexpected.)

Aargh!
rajat Maheshwari 6rajat Maheshwari 6

Hi Steve,

Please try to use Trigger.newMap.keyset() instead of theLeadID in query, and let me know if you still face the same issue? 

Thanks

Steve ThurstonSteve Thurston
Wow.  That seems to have done the trick!  I confess to being baffled why the old code didn't work anymore, but I'm glad you were able to provide me with an alternative!  Thank you!
Steve ThurstonSteve Thurston
Ahhhhhh, dangit!  I spoke to soon.  It worked twice, but on my next attempt, I get the same error, new message:

"System.QueryException: List has no rows for assignment to SObject"
Steve ThurstonSteve Thurston
This has something to do specifically with the Sandbox environment.  I refreshed my Sandbox just to make sure that I was using identical code in both Sandbox and Production.  Production works, Sandbox doesn't.
Steve ThurstonSteve Thurston
P.S. I looked for any hardcoded record IDs in the code, just to make sure, and didn't find any.
rajat Maheshwari 6rajat Maheshwari 6

Steve, 

Could you please share your sandbox credential on my email address : - rajatzmaheshwari@gmail.com ?

On my own side, I will do analyses and will get back to you

Thanks

Steve ThurstonSteve Thurston
It's a single user seat for my client, which is used for 3rd party integration, so I can't share the password.  I finally figured out what is going on.  There is another trigger that is used to identify and merge records that have the same email address.  i.e. when a new Lead is submitted, it checks for an existing Lead that has that email, and merges the two if it finds one.  It considered "null" to be the same email address. I'm not sure why, as that code was working fine before.  I think what's happening is that the two triggers are racing each other (they are both 'after insert').  
When the merge Leads trigger does its merge, it deletes the record that my round robin is working on.  It seems to always delete it at the same point in time.

I've now updated the code so that the merge Leads trigger once again doesn't recognize an email address of 'null' as a matching email address, so I no longer get an error on the round robin trigger when the email is null.  Both triggers also work correctly if the email is not a duplicate.  Even if the emails match, I now abort the round robin trigger.  But now, if there is a matching email, I get an error that the record has been deleted.  Not a messy error, but a good, proper UI error generated by Salesforce.  It's happening because it is trying to return to the *deleted* Lead record, rather than the merged record.

Problem:  I want to redirect the User to the merged Lead, which means I need to modify the URL.  Lots of messages indicate that you need to use VF to do this.  I have the following issue that I'm not sure if it matters:  99 times out of 100 this new Lead isn't going to be generated from the "New Lead" page.  It's being created by a third party API call.

I can override the 'Save' button on the new Lead page, but do I need to worry about this when the record is created via API?  There is no URL I'm coming from in that scenario.

I think I have seen something where the solution is to create a master trigger that calls one class first (merge duplicate Leads) and then calls the second class (round robin assignment).  I would preferably do something that doesn't require quite as much re-jiggering of the code.