{"record":{"id":"4daf729ed3fb6416","repo":"mongodb/laravel-mongodb","slug":"aggregation-builder-does-not-support-previous-query-builder","errorCode":null,"errorMessage":"Aggregation builder does not support previous query-builder instructions. Use a $match stage instead.","messagePattern":"Aggregation builder does not support previous query-builder instructions\\. Use a \\$match stage instead\\.","errorType":"exception","errorClass":"BadMethodCallException","httpStatus":null,"severity":"error","filePath":"src/Query/Builder.php","lineNumber":586,"sourceCode":"\n    /** @return ($function is null ? AggregationBuilder : mixed) */\n    #[Override]\n    public function aggregate($function = null, $columns = ['*'])\n    {\n        assert(is_array($columns), new TypeError(sprintf('Argument #2 ($columns) must be of type array, %s given', get_debug_type($columns))));\n\n        if ($function === null) {\n            if (! trait_exists(FluentFactoryTrait::class)) {\n                // This error will be unreachable when the mongodb/builder package will be merged into mongodb/mongodb\n                throw new BadMethodCallException('Aggregation builder requires package mongodb/builder 0.2+');\n            }\n\n            if ($columns !== ['*']) {\n                throw new InvalidArgumentException('Columns cannot be specified to create an aggregation builder. Add a $project stage instead.');\n            }\n\n            if ($this->wheres) {\n                throw new BadMethodCallException('Aggregation builder does not support previous query-builder instructions. Use a $match stage instead.');\n            }\n\n            return new AggregationBuilder($this->collection, $this->options);\n        }\n\n        $this->aggregate = [\n            'function' => $function,\n            'columns' => $columns,\n        ];\n\n        $previousColumns = $this->columns;\n\n        // We will also back up the select bindings since the select clause will be\n        // removed when performing the aggregate function. Once the query is run\n        // we will add the bindings back onto this query so they can get used.\n        $previousSelectBindings = $this->bindings['select'];\n\n        $this->bindings['select'] = [];","sourceCodeStart":568,"sourceCodeEnd":604,"githubUrl":"https://github.com/mongodb/laravel-mongodb/blob/0634653039468ceb0268a69192bdac64469ed043/src/Query/Builder.php#L568-L604","documentation":"The fluent AggregationBuilder starts from a clean pipeline; existing query-builder where clauses cannot be converted automatically. If ->where() etc. were applied before calling ->aggregate() with no function, this BadMethodCallException is thrown, directing you to use a $match stage.","triggerScenarios":"Chaining like Model::where('status','active')->aggregate(null) — wheres are non-empty when the fluent builder path runs.","commonSituations":"Developers reusing an existing filtered query object and switching to the aggregation builder, expecting filters to be preserved.","solutions":["Move each ->where(...) condition into a ->match(...) stage on the AggregationBuilder.","Call aggregate(null) on a fresh, unfiltered Builder instance.","If you want where-clauses translated for you, use aggregateRaw()/group aggregations instead of the fluent builder."],"exampleFix":"// before\nModel::where('status', 'active')->aggregate(null);\n// after\nModel::aggregate(null)->match('status', 'active');","handlingStrategy":"validation","validationCode":"if (! empty($query->getQuery()->wheres)) {\n    // convert wheres to a $match stage before the fluent builder call\n}\n$agg = $fresh = Model::query()->aggregate(null);","typeGuard":"function hasQueryBuilderState(Illuminate\\Database\\Eloquent\\Builder $q): bool { return ! empty($q->getQuery()->wheres); }","tryCatchPattern":"try {\n    $agg = $query->aggregate(null);\n} catch (BadMethodCallException $e) {\n    if (str_contains($e->getMessage(), '$match stage')) {\n        $agg = $query->getModel()->query()->aggregate(null)->match('status', 'active');\n    } else { throw $e; }\n}","preventionTips":["Start fluent aggregation from a fresh Model::query(), not a filtered builder","Express filters via ->match(...) stages on the AggregationBuilder","Audit helpers that accept a Builder and call aggregate(null)","Write tests covering mixed where()+aggregate(null) usage"],"tags":["aggregation","match","builder"],"backgroundTag":"unsupported-operation","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"}