{"record":{"id":"fea5cf90b7ecc85f","repo":"mongodb/laravel-mongodb","slug":"cannot-sort-by-a-field-named-score-together-with-atlas","errorCode":null,"errorMessage":"Cannot sort by a field named 'score' together with Atlas Search's '_score' relevance sort.","messagePattern":"Cannot sort by a field named 'score' together with Atlas Search's '_score' relevance sort\\.","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/Scout/ScoutEngine.php","lineNumber":204,"sourceCode":"    {\n        assert(is_int($perPage), new TypeError(sprintf('Argument #2 ($perPage) must be of type int, %s given', get_debug_type($perPage))));\n        assert(is_int($page), new TypeError(sprintf('Argument #3 ($page) must be of type int, %s given', get_debug_type($page))));\n\n        $builder = clone $builder;\n        $builder->take($perPage);\n\n        return $this->performSearch($builder, $perPage * ($page - 1));\n    }\n\n    /**\n     * Perform the given search on the engine.\n     */\n    private function performSearch(Builder $builder, ?int $offset = null): array\n    {\n        // Validate sort before any I/O so unit tests can assert on these exceptions without a real collection.\n        $columns = array_column($builder->orders, 'column');\n        if (in_array('_score', $columns, true) && in_array('score', $columns, true)) {\n            throw new InvalidArgumentException(\"Cannot sort by a field named 'score' together with Atlas Search's '_score' relevance sort.\");\n        }\n\n        foreach ($builder->orders as $order) {\n            if ($order['column'] === '_score' && $order['direction'] === 'asc') {\n                throw new InvalidArgumentException(\"Cannot sort by '_score' in ascending order; Atlas Search relevance score always sorts descending.\");\n            }\n        }\n\n        $collection = $this->getSearchableCollection($builder->model);\n\n        if ($builder->callback) {\n            $cursor = call_user_func(\n                $builder->callback,\n                $collection,\n                $builder->query,\n                $offset,\n            );\n            assert($cursor instanceof CursorInterface, new LogicException(sprintf('The search builder closure must return a MongoDB cursor, %s returned', get_debug_type($cursor))));","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/mongodb/laravel-mongodb/blob/0634653039468ceb0268a69192bdac64469ed043/src/Scout/ScoutEngine.php#L186-L222","documentation":"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.","triggerScenarios":"Calling ScoutEngine::search()/paginate() with a Laravel Scout Builder whose orders contain both column '_score' and column 'score' (e.g. ->orderBy('_score')->orderBy('score')).","commonSituations":"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.","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"],"exampleFix":"// before\n$builder->orderBy('_score')->orderBy('score');\n// after\n$builder->orderBy('_score')->orderBy('user_score'); // field renamed in documents/mappings","handlingStrategy":"validation","validationCode":"$cols = array_column($builder->orders, 'column');\nif (in_array('_score', $cols, true) && in_array('score', $cols, true)) {\n    throw new InvalidArgumentException(\"Cannot combine 'score' and '_score' sorts.\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    $results = $model->search($q)->orderBy('_score')->orderBy('score')->get();\n} catch (\\InvalidArgumentException $e) {\n    $results = $model->search($q)->orderBy('_score')->get(); // drop the conflicting sort\n}","preventionTips":["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')"],"tags":["php","laravel-scout","atlas-search","sorting"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"0634653039468ceb0268a69192bdac64469ed043","analyzedAt":"2026-09-15T02:56:37.067Z","contentChangedAt":"2026-09-15T02:56:37.067Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}