Skip to main content

Known Issues

Variable does not exist

Error: System.QueryException: Variable does not exist: v1

Root Cause

This is NOT a SOQL Lib issue but rather a Salesforce platform limitation that occurs when Database.getQueryLocatorWithBinds is used with insufficient field-level security permissions.

This error occurs when all of the following conditions are met:

  • toQueryLocator() method is executed
  • Query is executed with USER_MODE (which is the default access level if not otherwise specified)
  • Query contains fields to which the current user lacks read access permissions
  • Query includes at least one WHERE condition, resulting in a non-empty binding map
  • The Salesforce platform fails to validate field access permissions before processing bound variables

Example that fails:

Native Apex

Database.getQueryLocatorWithBinds(
'SELECT Type FROM Task WHERE Type != :v1',
new Map<String, Object>{'v1' => null},
AccessLevel.USER_MODE
);

SOQL Lib

SOQL.of(Task.SObjectType)
.with(Task.Type) // <== User lacks read access to this field
.whereAre(SOQL.Filter.with(Task.Type).isNotNull())
.toQueryLocator();

Technical Context

The error occurs because Salesforce's Database.getQueryLocatorWithBinds method attempts to validate bound variables before performing field-level security checks. When the user lacks access to fields referenced in the query, the platform cannot properly resolve the bound variables, resulting in the misleading "Variable does not exist" error message instead of a more accurate field access permission error.

Solutions

Option 1: Grant Field Access Permissions

Grant the current user appropriate field-level security permissions for all fields referenced in the query through:

  • Profile Settings: Update the user's profile to include read access to the required fields
  • Permission Sets: Assign permission sets that grant access to the necessary fields
  • Field-Level Security: Configure field-level security settings for the specific fields

Option 2: Use SYSTEM_MODE

Execute the query with elevated permissions using SYSTEM_MODE to bypass field-level security restrictions:

Native Apex

Database.getQueryLocatorWithBinds(
'SELECT Type FROM Task WHERE Type != :v1',
new Map<String, Object>{'v1' => null},
AccessLevel.SYSTEM_MODE
);

SOQL Lib

SOQL.of(Task.SObjectType)
.with(Task.Type)
.whereAre(SOQL.Filter.with(Task.Type).isNotNull())
.systemMode() // <== Bypasses field-level security
.toQueryLocator();

Security Consideration: Use SYSTEM_MODE judiciously as it bypasses security controls and may expose sensitive data to unauthorized users.

Variable does not exist: SObjectType

Error: Error: Variable does not exist: SObjectType

Root Cause

This error occurs due to Apex variable name conflicts when a local variable name matches the SObjectType class name used in the SOQL query. Apex's compiler becomes confused between the local variable reference and the SObjectType static reference, leading to compilation errors.

Example that fails:

Contact contact = new Contact(FirstName = 'Test', LastName = 'Test');

List<Contact> contacts = SOQL.of(Contact.SObjectType) // <== Conflict with 'contact' variable
.with(Contact.Id, Contact.Name)
.setLimit(10)
.toList();

Technical Context

In Apex, when you declare a variable with the same name as an SObjectType (e.g., Contact contact), the compiler prioritizes the local variable scope over the static class reference. This causes Contact.SObjectType to be interpreted as attempting to access a property on the local contact variable rather than the static Contact class, resulting in the compilation error.

Solution

Use Distinct Variable Names

Ensure local variable names are distinct from SObjectType class names to avoid namespace conflicts:

Example that works:

Contact contactRecord = new Contact(FirstName = 'Test', LastName = 'Test');

List<Contact> contacts = SOQL.of(Contact.SObjectType)
.with(Contact.Id, Contact.Name)
.setLimit(10)
.toList();

Method does not exist or incorrect signature: void of(Schema.SObjectField)

Error: Error: Method does not exist or incorrect signature: void of(Schema.SObjectField) from the type SOQL

Root Cause

This error occurs due to Salesforce's incomplete SObjectType implementation for certain system objects. The issue stems from Salesforce's internal architecture where certain objects are treated as "pseudo-SObjects" that don't fully implement the standard SObject interface, leading to missing or incomplete method signatures.

Technical Context

Primary Object Affected:

  • RecordType

Example that fails:

SOQL.of(RecordType.SObjectType)
.setLimit(1)
.toObject();

Solution

Use String API Name Instead of SObjectType

Use SOQL.of('RecordType') with the string API name instead of using the SObjectType reference.

Example that works:

SOQL.of('RecordType')
.setLimit(1)
.toObject();