System.QueryException: List has no rows for assignment to SObject
You assigned a SOQL result directly to a single record variable, but the query matched zero rows. Apex can't assign "nothing" to a non-nullable variable, so it throws.
Also seen asList has no rows for assignment to SObject·System.QueryException: List has no rows·QueryException List has no rows
This is a single-line Apex idiom that backfires the moment the database is empty.
// If no Account is named 'Foo', this line throws.
Account a = [SELECT Id, Name FROM Account WHERE Name = 'Foo' LIMIT 1];
When you assign a SOQL query directly to an SObject variable, Apex requires exactly one row. Zero throws QueryException: List has no rows for assignment to SObject. More than one throws a different error (assignment to SObject from non-singleton list).
Why it's especially nasty
It only fails when the data isn't there — so it passes every test in your sandbox where the data is there, then explodes in production the first time someone deletes the record, renames it, or runs the code in a brand-new org.
The fix
Always query into a List and check the size yourself. The List form returns an empty list (which is valid) instead of throwing.
List<Account> hits = [SELECT Id, Name FROM Account WHERE Name = 'Foo' LIMIT 1];
if (hits.isEmpty()) {
// Decide: return early, throw a meaningful error, create a default, etc.
return null;
}
Account a = hits[0];
Or, if the row is genuinely required by your business logic, throw an error that says what's wrong:
List<Account> hits = [SELECT Id FROM Account WHERE Name = :term LIMIT 1];
if (hits.isEmpty()) {
throw new IllegalArgumentException('Required Account "' + term + '" not found.');
}
A clear error message saves an hour of triage compared to the cryptic stock message.
When to prefer [SELECT ... LIMIT 1][0]
Don't. It throws two different exceptions depending on whether the list is empty or non-empty (List index out of bounds: 0 for empty), and looks like a clever shortcut to anyone reading it. The List<Foo> hits = [...]; if (hits.isEmpty()) pattern is two extra lines and saves you from both failure modes.
