I keep getting the error:

System.QueryException: expecting a colon, found 'setids'

Why do I get this error? How can I fix it?

public Database.QueryLocator start(Database.BatchableContext context) {
    Set<Id> setids = new Set<Id>();
    for(Task t : [SELECT WhatId FROM Task WHERE Is_Precall__c = true AND Is_Created_By_Batch__c = true AND CreatedDate = TODAY]){

    String q = 'SELECT Id, Route_Lookup__c, Next_Delivery_Date__c,';
         q += ' Market_Center_Lookup__c,';
         q += ' (SELECT Id FROM Orders__r WHERE Status = \'Pending\')';
         q += ' FROM ServicePoint__c WHERE Type__c = \'Active\'';
         q += ' AND Is_Batch_Exec_Date__c = true';
         q += ' AND Is_Precall_Customer__c = true';
         q += ' AND Id NOT IN setids' ;
    return Database.getQueryLocator(q);
  • 1
    replace setids by :setids
    – kurunve
    Commented Jul 5, 2017 at 14:07
  • 1
    Drive-by downvoting is bad, people (shame on whoever did it). If I had to guess why this got downvoted, I'd say that it was because it is a pretty basic question which may have been able to be resolved by searching/googling for the error message. That said, this question contained the error message as well as the relevant code that was producing the error. I don't generally upvote questions that don't show research effort, but I will here to offset what I see as an undeserved downvote.
    – Derek F
    Commented Jul 5, 2017 at 14:50
  • As an aside, Database.getQueryLocator can also accept an inline query, which avoids runtime errors by having the compiler warn you during deployment/development. You should use the string version only when you cannot predict the fields or conditions in advance.
    – sfdcfox
    Commented Jul 5, 2017 at 17:26

2 Answers 2


When you reference an apex variable in a query (standard, or dynamic as is your case), you need to prefix the variable name with a colon :. This is called expression binding. You can still use expression binding in dynamic soql. Though there are some additional considerations when using this with dynamic soql, I don't believe any of them apply in this particular case.

The line in question here is

q += ' AND Id NOT IN setids' ;

and the correct way to do this would be

// Notice the colon (:) added before setids
q += ' AND Id NOT IN :setids';

Your passing set variable setids to an queryLocator on this line ,

q += ' AND Id NOT IN setids' ;

make correction on that line

q += ' AND Id NOT IN : setids' ; //add : before setids
  • I don't think that the particular question you linked to is too relevant to the question being asked here. There is a passing resemblance, but OP (Original Poster of the question) isn't trying to do anything near that level of complexity.
    – Derek F
    Commented Jul 5, 2017 at 15:00

You must log in to answer this question.

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