I'm rolling out a new batch process and started getting Invalid Query Locator error messages on certain batches (4 out of 85). Am I doing something wrong?

Start Method

String query = 'select field1__c, (select field2__c from Details__r) from Master__c';
return Database.getQueryLocator(query);

Execute Method

for(Master__c m : (List<Master__c>) scope) {
  for(Detail__c d : m.Details__r) { // THROWS INVALID QUERY LOCATOR ERROR
    // processing

1 Answer 1


Other than the "detials" typo :) - you can get this error when your sub-relationship query (in this case Details__r), returns too many records (I think over 200). Is that possibly the case for some of your larger relationships?

According to the docs you referenced, this error may also occur in cases where the sub-query's QueryLocator expires or is "released" by the code. To me the takeaway from that is that batch jobs with QueryLocators should avoid sub-queries at all costs, and move the sub-querying logic into the execute method.

So your best bet probably is to do the sub-relationship query as part of the execute method (and with that, you may need to reduce your batch size depending on total data size).

  • Yep, looks like the current max is 318. Is the 200 record limit documented somewhere? Generally I avoid sub-queries completely because they seem to be buggy (not my code) and I think I've ran into the 200 one before, but am curious if I should still be logging a bug or if this is working as designed. Commented Mar 19, 2013 at 4:17
  • Couldn't find explicit documentation on it, other than a bunch of third party blog posts mentioning it, which isn't to say it's undocumented. The "for loop batch size" limit is documented in the governor limits reference, which you are possibly violating as well although I believe you would probably hit the error you're seeing if you accessed the relationship outside of a loop as well. That would be a worthwhile test though.
    – jkraybill
    Commented Mar 19, 2013 at 4:22
  • 1
    Well this is a first, starting submitted a case and got a solution that addressed my actual issue. Doesn't appear to have anything to do with 200 though, instead the sub-queries are held with query locators which can on occassion expire, see help.salesforce.com/…. Going to test out a bit to confirm. Commented Mar 19, 2013 at 4:30
  • Wow that's never happened to me either :) Based on that documentation, the sure takeaway should be "never use sub-queries in query locators" (or possibly ever).
    – jkraybill
    Commented Mar 19, 2013 at 4:34
  • Want to update the answer and I'll re-accept (sorry had to undo the first one, you got me where I needed, but it's not correct yet)? Just tested by using a subquery on the five Master__c with the most Detial__c (around 300 each), and then just looped over everything. No errors. Commented Mar 19, 2013 at 4:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .