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

System.QueryException: List has no rows for assignment to SObject

What does this error mean?

When you write Account a = [SELECT Id FROM Account WHERE ...] and the query returns no records, Salesforce has nothing to assign to the variable a. Rather than assigning null, Salesforce throws this exception. The error occurs because the inline SOQL assignment syntax implicitly expects exactly one record.

This error can also occur when the running user does not have access to view the queried record — the query returns 0 rows due to record-level security, even if the record exists.

Common Causes

1. Record doesn't exist

Querying by a hardcoded or dynamic ID that no longer exists in the org — for example, a record that was deleted between when the ID was captured and when the query runs.

2. WHERE clause too restrictive

A filter combination that matches no records — common in test classes where setup data doesn't exactly match the query conditions used in production logic.

3. Insufficient record access

The running user doesn't have sharing access to the record. With with sharing on the class, the query respects record-level security and returns 0 rows even if the record exists.

How to Fix It

Solution 1: Query into a List and check size

Always query into a List<SObject> and check its size before accessing the first element. This is the safest and most readable pattern.

Apex
// ❌ BAD — throws if no record found
Account acc = [SELECT Id, Name FROM Account WHERE Id = :recordId];

// ✅ GOOD — safe pattern
List<Account> accounts = [
    SELECT Id, Name
    FROM Account
    WHERE Id = :recordId
    LIMIT 1
];

if (!accounts.isEmpty()) {{
    Account acc = accounts[0];
    // safe to use acc here
}}

Solution 2: Use the null-coalescing operator (Spring '24+)

Salesforce introduced the ?? operator in Spring '24. It returns a default value when the left-hand expression is null, allowing safe inline SOQL assignment.

Apex
// ✅ Returns a blank Account if no rows found (Spring '24+)
Account acc = [
    SELECT Id, Name
    FROM Account
    WHERE Id = :recordId
] ?? new Account();

if (acc.Id != null) {{
    // record was found
}}

Solution 3: Wrap in try/catch where appropriate

In legacy code or where refactoring isn't feasible, wrap the assignment in a try/catch. This is less preferred because it uses exception handling as control flow.

Apex
Account acc;
try {{
    acc = [SELECT Id, Name FROM Account WHERE Id = :recordId];
}} catch (System.QueryException e) {{
    // No record found — handle gracefully
    System.debug('Record not found: ' + recordId);
}}
lightbulb

Pro Tip: Always add LIMIT 1 to queries that are expected to return a single record. It makes intent explicit, improves performance, and prevents a different error if the query unexpectedly returns multiple rows.