mongodb/laravel-mongodb · error · InvalidArgumentException
Cannot sort by a field named 'score' together with Atlas…
Error message
Cannot sort by a field named 'score' together with Atlas Search's '_score' relevance sort.
What it means
The Atlas Search Scout engine maps the special '_score' order to relevance ranking. If the query also sorts by a user field literally named 'score', the two orders are ambiguous/conflicting, so an InvalidArgumentException is thrown before any I/O.
Solutions
- Rename the model field from 'score' to something like 'user_score' in documents and mappings
- Drop the explicit orderBy('score') when ordering by '_score' relevance
- Wrap the field, e.g. sort on 'stats.score' instead of 'score', to avoid the reserved-name clash
- Catch InvalidArgumentException in the search path to surface a clear user-facing message
Example fix
// before
$builder->orderBy('_score')->orderBy('score');
// after
$builder->orderBy('_score')->orderBy('user_score'); // field renamed in documents/mappings Defensive patterns
Strategy: validation
Validate before calling
$cols = array_column($builder->orders, 'column');
if (in_array('_score', $cols, true) && in_array('score', $cols, true)) {
throw new InvalidArgumentException("Cannot combine 'score' and '_score' sorts.");
} Try / catch
try {
$results = $model->search($q)->orderBy('_score')->orderBy('score')->get();
} catch (\InvalidArgumentException $e) {
$results = $model->search($q)->orderBy('_score')->get(); // drop the conflicting sort
} Prevention
- Avoid naming searchable fields 'score' in Atlas-Search-backed models
- Centralize sort construction so '_score' and 'score' cannot both be appended
- Review default model scopes that add orderBy('score')
When it happens
Trigger: Calling ScoutEngine::search()/paginate() with a Laravel Scout Builder whose orders contain both column '_score' and column 'score' (e.g. ->orderBy('_score')->orderBy('score')).
Common situations: Models that legitimately have a 'score' field being searched with Atlas Search relevance sort; combining app-level default ordering with a relevance sort added in the search flow.
Related errors
- Cannot sort by '_score' in ascending order; Atlas Search…
- Invalid search index definition for collection
- Atlas search index operation time out after
- The MongoDB Scout collection
- Between $values must be a list with exactly two elements…
AI-assisted analysis of mongodb/laravel-mongodb@0634653039 (2026-09-15).
Data as JSON: /api/errors/fea5cf90b7ecc85f.
Report an issue: GitHub.
Appendix: source
Thrown at src/Scout/ScoutEngine.php:204
{
assert(is_int($perPage), new TypeError(sprintf('Argument #2 ($perPage) must be of type int, %s given', get_debug_type($perPage))));
assert(is_int($page), new TypeError(sprintf('Argument #3 ($page) must be of type int, %s given', get_debug_type($page))));
$builder = clone $builder;
$builder->take($perPage);
return $this->performSearch($builder, $perPage * ($page - 1));
}
/**
* Perform the given search on the engine.
*/
private function performSearch(Builder $builder, ?int $offset = null): array
{
// Validate sort before any I/O so unit tests can assert on these exceptions without a real collection.
$columns = array_column($builder->orders, 'column');
if (in_array('_score', $columns, true) && in_array('score', $columns, true)) {
throw new InvalidArgumentException("Cannot sort by a field named 'score' together with Atlas Search's '_score' relevance sort.");
}
foreach ($builder->orders as $order) {
if ($order['column'] === '_score' && $order['direction'] === 'asc') {
throw new InvalidArgumentException("Cannot sort by '_score' in ascending order; Atlas Search relevance score always sorts descending.");
}
}
$collection = $this->getSearchableCollection($builder->model);
if ($builder->callback) {
$cursor = call_user_func(
$builder->callback,
$collection,
$builder->query,
$offset,
);
assert($cursor instanceof CursorInterface, new LogicException(sprintf('The search builder closure must return a MongoDB cursor, %s returned', get_debug_type($cursor))));View on GitHub (pinned to 0634653039)