{"record":{"id":"3b5fd4d47d93e764","repo":"mongodb/laravel-mongodb","slug":"a-pipeline-exceeds-the-maximum-of-d-stages","errorCode":null,"errorMessage":"A pipeline exceeds the maximum of %d stages.","messagePattern":"A pipeline exceeds the maximum of (.+?) stages\\.","errorType":"exception","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/Tools/DatabaseQuery.php","lineNumber":137,"sourceCode":"            $this->ensureNoNestedWriteInAggregation($command['pipeline'] ?? []);\n        }\n\n        return $connection->getDatabase()->command($command)->toArray();\n    }\n\n    /**\n     * @param array<int, array<string, mixed>> $pipeline\n     *\n     * @throws InvalidArgumentException\n     */\n    private function ensureNoNestedWriteInAggregation(array $pipeline, int $level = 1): void\n    {\n        if ($level > self::MAX_NESTING_LEVEL) {\n            throw new InvalidArgumentException(sprintf('Aggregation nesting exceeds the maximum of %d levels.', self::MAX_NESTING_LEVEL));\n        }\n\n        if (count($pipeline) > self::MAX_STAGES_PER_PIPELINE) {\n            throw new InvalidArgumentException(sprintf('A pipeline exceeds the maximum of %d stages.', self::MAX_STAGES_PER_PIPELINE));\n        }\n\n        // These aggregation stages may contain nested aggregation pipelines\n        // and must be checked for write ops recursively.\n        $supportsNestedWrites = ['facet', 'lookup', 'unionWith'];\n\n        // Every known read-only aggregation stage. Kept as an allow list (rather than\n        // denying $merge/$out) so that write stages added in the future are rejected by\n        // default. See https://www.mongodb.com/docs/manual/reference/mql/aggregation-stages\n        $allowList = array_merge($supportsNestedWrites, [\n            'addFields',\n            'bucket',\n            'bucketAuto',\n            'changeStream',\n            'changeStreamSplitLargeEvent',\n            'collStats',\n            'count',\n            'currentOp',","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/mongodb/laravel-mongodb/blob/0634653039468ceb0268a69192bdac64469ed043/src/Tools/DatabaseQuery.php#L119-L155","documentation":"One of the aggregation pipelines in the command (top-level or a sub-pipeline inside $facet/$lookup/$unionWith) has more than 1000 stages, matching MongoDB's documented pipeline stage limit. The library rejects it up front instead of letting the server fail.","triggerScenarios":"An aggregate command with a `pipeline` array longer than 1000 entries, or any nested sub-pipeline (inside $facet, $lookup.pipeline, $unionWith.pipeline) exceeding 1000 stages.","commonSituations":"Programmatically generated pipelines that unroll thousands of $match/$addFields stages; bulk-converted query builders; AI-generated pipelines that repeat stages instead of using $in or aggregation expressions.","solutions":["Reduce the number of stages to 1000 or fewer, merging consecutive $match stages into one with $and or $in.","Combine consecutive expression stages (e.g. many $addFields into one $addFields document).","Filter data before the pipeline (e.g. in application code or with a $match on indexed fields) rather than chaining hundreds of stages."],"exampleFix":"// before: pipeline with 1500 entries, one {\"$match\": {\"status\": \"s\"}} per status\n// after\n{\"aggregate\": \"users\", \"pipeline\": [{\"$match\": {\"status\": {\"$in\": [\"a\", \"b\", \"c\"]}}}, {\"$limit\": 100}]}","handlingStrategy":"validation","validationCode":"$countStages = fn (array $p): int => array_sum(array_map(\n    fn ($s) => ((string) array_key_first($s) === '$facet' && is_array($s['$facet']))\n        ? array_sum(array_map($countStages, $s['$facet']))\n        : 1,\n    $p\n));\nif (count($pipeline) > 1000) { throw new \\InvalidArgumentException('pipeline has more than 1000 stages'); }","typeGuard":null,"tryCatchPattern":"try {\n    $result = $tool->handle($request);\n} catch (\\InvalidArgumentException $e) {\n    if (str_contains($e->getMessage(), 'maximum of 1000 stages')) {\n        // merge/collapse stages and retry\n    }\n}","preventionTips":["Merge consecutive $match stages using $and / $in.","Combine repeated $addFields into a single stage document.","Count pipeline entries programmatically before dispatching large generated pipelines."],"tags":["mongodb","aggregation","pipeline-limit","mcp-tool"],"backgroundTag":"value-out-of-range","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"}