home Homebuild Toolsbug_report Errorsmenu_book Guideslightbulb Tipssmart_toy Promptsextension Extensionsfolder_open Resourcesinfo About
search
error

System.QueryException: Only variable references are allowed in dynamic SOQL/SOSL

What does this error mean?

In dynamic SOQL (queries built as strings and run with Database.query()), bind variable syntax — using : before a name — must reference an Apex variable that exists in the current scope. You cannot use a literal value like :'someString' or :0050W000007Jz7jQAC directly in the query string. Salesforce evaluates the bind expression against the Apex runtime scope, not the string content.

Common Causes

1. Hardcoded ID literal in bind position

Writing WHERE OwnerId =: 0050W000007Jz7jQAC inside a dynamic query string. The colon-prefixed value must be a variable name, not a literal ID.

2. String literal in bind position

Something like 'WHERE Status__c =: \'Active\'' — the value after : must be an Apex variable identifier.

3. Confusion between static and dynamic SOQL syntax

Static SOQL (inline brackets) evaluates bind variables at parse time and can reference any in-scope variable. Dynamic SOQL uses the same syntax but evaluates at runtime — the variable must be in scope when Database.query() is called.

How to Fix It

Solution 1: Assign the value to a variable first

Always assign any value you want to bind to a named Apex variable before including it in the query string.

Apex
// ❌ BAD — literal ID in bind position
String soql = 'SELECT Id FROM User WHERE Id =: 0050W000007Jz7jQAC';

// ✅ GOOD — variable in scope
Id targetId = '0050W000007Jz7jQAC';
String soql = 'SELECT Id FROM User WHERE Id = :targetId';
List<User> results = Database.query(soql);

// ✅ Also works — string literal in variable
String statusFilter = 'Active';
String soql2 = 'SELECT Id FROM Account WHERE Status__c = :statusFilter';

Solution 2: Use string interpolation for non-sensitive values

For values that don't come from user input, you can safely interpolate them directly into the query string using String.escapeSingleQuotes() to prevent SOQL injection.

Apex
// ✅ Safe interpolation for trusted internal values
String safeStatus = String.escapeSingleQuotes('Active');
String soql = 'SELECT Id FROM Account WHERE Status__c = \' + safeStatus + '\';

// ⚠️ NEVER interpolate user-provided input without escaping
// Use bind variables (:varName) for user input — always
security

Security note: Always use bind variable syntax (:variableName) for any value derived from user input. Never concatenate user-provided values into SOQL strings — this opens a SOQL injection vulnerability. Only use string interpolation for values you fully control.