laravel/framework · error · MultipleRecordsFoundException
%s records were found.
Error message
%s records were found.
What it means
Relation::sole() (and Builder::sole()) fetch up to 2 rows and require exactly one. If more than one row matches, MultipleRecordsFoundException (RuntimeException) is thrown with the count, because 'sole' asserts the caller's expectation of uniqueness. It is distinct from ModelNotFoundException (zero rows).
Source
Thrown at src/Illuminate/Database/Eloquent/Relations/Relation.php:271
*
* @param array|string $columns
* @return TRelatedModel
*
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException<TRelatedModel>
* @throws \Illuminate\Database\MultipleRecordsFoundException
*/
public function sole($columns = ['*'])
{
$result = $this->limit(2)->get($columns);
$count = $result->count();
if ($count === 0) {
throw (new ModelNotFoundException)->setModel(get_class($this->related));
}
if ($count > 1) {
throw new MultipleRecordsFoundException($count);
}
return $result->first();
}
/**
* Execute the query as a "select" statement.
*
* @param array $columns
* @return \Illuminate\Database\Eloquent\Collection<int, TRelatedModel>
*/
public function get($columns = ['*'])
{
return $this->query->get($columns);
}
/**
* Touch all of the related models for the relationship.View on GitHub (pinned to bd6b5437e6)
Solutions
- Use first() or firstOrFail() if more than one row may legitimately match.
- Add a unique constraint/index at the DB level to enforce the uniqueness sole() assumes.
- Tighten the where clause to guarantee a single row (e.g. add scope/order+limit 1 explicitly).
- Catch MultipleRecordsFoundException to handle the ambiguity explicitly.
Example fix
// before
$post = User::where('slug', $slug)->sole(); // throws if duplicate slugs
// after
$post = User::where('slug', $slug)->firstOrFail();
// or enforce uniqueness:
// schema: $table->string('slug')->unique(); Defensive patterns
Strategy: try-catch
Validate before calling
if ($query->count() > 1) {
throw new \Illuminate\Database\MultipleRecordsFoundException($query->count());
}
$query->sole(); Type guard
function isUniqueMatch(\Illuminate\Database\Eloquent\Builder $query): bool {
return $query->clone()->limit(2)->count() === 1;
} Try / catch
try {
return $query->sole();
} catch (\Illuminate\Database\MultipleRecordsFoundException $e) {
// handle ambiguity: pick one, log, or fail
return $query->first();
} Prevention
- Add unique indexes for columns queried with sole().
- Use first()/firstOrFail() when duplicates may legitimately exist.
- Tighten where clauses to guarantee a single row.
When it happens
Trigger: Calling ->sole() on a relation or query that matches 2+ rows, e.g. User::where('email', $e)->sole() when duplicates exist, or $user->latestPost()->sole() when there are multiple.
Common situations: Data with unintended duplicates (missing unique index); querying by a non-unique column; race conditions inserting duplicates before a unique constraint; using sole() where first() was intended.
Related errors
- $count records were found.
- $count items were found.
- The chunkById operation was aborted because the [{$alias}] c
- No record found for the given query.
- Property [{$key}] does not exist on the Eloquent builder ins
AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06).
Data as JSON: /data/errors/1d03ca45add880c9.json.
Report an issue: GitHub.