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

MALFORMED_QUERY: Semi-joins are only supported in WHERE clauses

What does this error mean?

SOQL supports two types of subqueries: relationship subqueries in the SELECT clause (e.g., SELECT Id, (SELECT Id FROM Contacts) FROM Account) and semijoins / anti-semijoins in the WHERE clause (e.g., WHERE Id IN (SELECT AccountId FROM Contact)). Attempting to use a semijoin-style subquery in the SELECT clause or other unsupported position triggers this error.

Common Causes

1. Semijoin subquery in SELECT clause

Trying to return subquery results as a standalone column, which is valid SQL but not SOQL: SELECT (SELECT COUNT() FROM Contacts) FROM Account in a non-relationship context.

2. Nested semijoins

SOQL does not support subqueries nested inside other subqueries beyond one level. A WHERE Id IN (SELECT Id FROM X WHERE Id IN (SELECT ...)) pattern will fail.

How to Fix It

Solution 1: Move semijoin to the WHERE clause

SOQL
-- ❌ INVALID — semijoin in SELECT
SELECT Id, (SELECT COUNT() FROM Contact WHERE AccountId = Account.Id)
FROM Account

-- ✅ CORRECT — semijoin in WHERE
SELECT Id, Name
FROM Account
WHERE Id IN (SELECT AccountId FROM Contact WHERE LeadSource = 'Web')

-- ✅ CORRECT — relationship subquery in SELECT (different syntax)
SELECT Id, Name, (SELECT Id, Email FROM Contacts)
FROM Account

Solution 2: Break into two queries in Apex

For complex filtering that would require nested semijoins, use two separate queries in Apex and filter the second using the results of the first.

Apex
// Step 1: get the IDs from the inner condition
Set<Id> contactAccountIds = new Set<Id>();
for (Contact c : [SELECT AccountId FROM Contact WHERE LeadSource = 'Web']) {{
    contactAccountIds.add(c.AccountId);
}}

// Step 2: use the set in the outer query
List<Account> accounts = [
    SELECT Id, Name
    FROM Account
    WHERE Id IN :contactAccountIds
];