laravel/framework · error · MultipleItemsFoundException

$count items were found.

Error message

$count items were found.

What it means

Thrown by Arr::sole() (via MultipleItemsFoundException) when more than one item remains after applying the optional callback. sole() is the 'expect exactly one' accessor: zero items raises ItemNotFound, two or more raises this. The message reports how many were found.

Source

Thrown at src/Illuminate/Collections/Arr.php:1098

     * @param  (callable(mixed, array-key): array)|null  $callback
     *
     * @throws \Illuminate\Support\ItemNotFoundException
     * @throws \Illuminate\Support\MultipleItemsFoundException
     */
    public static function sole($array, ?callable $callback = null)
    {
        if ($callback) {
            $array = static::where($array, $callback);
        }

        $count = count($array);

        if ($count === 0) {
            throw new ItemNotFoundException;
        }

        if ($count > 1) {
            throw new MultipleItemsFoundException($count);
        }

        return static::first($array);
    }

    /**
     * Sort the array using the given callback or "dot" notation.
     *
     * @template TKey of array-key
     * @template TValue
     *
     * @param  iterable<TKey, TValue>  $array
     * @param  callable|string|null|array<int, (callable(TValue, TValue): -1|0|1)|array{string, SortDirection|'asc'|'desc'}>  $callback
     * @return array<TKey, TValue>
     */
    public static function sort($array, $callback = null)
    {
        return (new Collection($array))->sortBy($callback)->all();

View on GitHub (pinned to bd6b5437e6)

Solutions

  1. Tighten the predicate so only one element matches (filter by a unique identifier).
  2. Use Arr::first() if you don't actually need uniqueness.
  3. De-duplicate the source before calling sole().
  4. Guard: if (count($matches) !== 1) handle the ambiguous case explicitly.

Example fix

// before
$user = Arr::sole($users, fn ($u) => $u->team_id === $teamId);

// after
$user = Arr::sole($users, fn ($u) => $u->id === $expectedId);
// or accept any match
$user = Arr::first($users, fn ($u) => $u->team_id === $teamId);
Defensive patterns

Strategy: validation

Validate before calling

$matches = array_values(array_filter($users, $callback ?? fn () => true));
if (count($matches) !== 1) {
    // handle ambiguity explicitly instead of calling Arr::sole()
}

Type guard

function hasExactlyOne(array $array, ?callable $cb = null): bool {
    return count($cb ? array_filter($array, $cb) : $array) === 1;
}

Try / catch

try {
    $user = Arr::sole($users, fn ($u) => $u->team_id === $teamId);
} catch (\Illuminate\Collections\MultipleItemsFoundException $e) {
    // narrow the predicate or take the first match
    $user = Arr::first($users, fn ($u) => $u->id === $id);
} catch (\Illuminate\Collections\ItemNotFoundException $e) {
    $user = null;
}

Prevention

When it happens

Trigger: Calling Arr::sole($users) on a multi-element array, or Arr::sole($users, fn ($u) => $u->active) when several users match the predicate.

Common situations: Querying by a key that is supposedly unique but the dataset has duplicates; loose predicates (e.g. fn => true); a collection that was expected to be filtered down to one but wasn't.

Related errors


AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06). Data as JSON: /data/errors/dc39252a2d8e8ea1.json. Report an issue: GitHub.