{"record":{"id":"3c9b0f0bbb65d974","repo":"mongodb/node-mongodb-native","slug":"argument-pipeline-must-be-an-array-of-aggregatio","errorCode":null,"errorMessage":"Argument \"pipeline\" must be an array of aggregation stages","messagePattern":"Argument \"pipeline\" must be an array of aggregation stages","errorType":"exception","errorClass":"MongoInvalidArgumentError","httpStatus":null,"severity":"error","filePath":"src/collection.ts","lineNumber":1063,"sourceCode":"        filter,\n        update,\n        resolveOptions(this, options)\n      ) as TODO_NODE_3286\n    );\n  }\n\n  /**\n   * Execute an aggregation framework pipeline against the collection, needs MongoDB \\>= 2.2\n   *\n   * @param pipeline - An array of aggregation pipelines to execute\n   * @param options - Optional settings for the command\n   */\n  aggregate<T extends Document = Document>(\n    pipeline: Document[] = [],\n    options?: AggregateOptions & Abortable\n  ): AggregationCursor<T> {\n    if (!Array.isArray(pipeline)) {\n      throw new MongoInvalidArgumentError(\n        'Argument \"pipeline\" must be an array of aggregation stages'\n      );\n    }\n\n    return new AggregationCursor(\n      this.client,\n      this.s.namespace,\n      pipeline,\n      resolveOptions(this, options)\n    );\n  }\n\n  /**\n   * Create a new Change Stream, watching for new changes (insertions, updates, replacements, deletions, and invalidations) in this collection.\n   *\n   * @remarks\n   * watch() accepts two generic arguments for distinct use cases:\n   * - The first is to override the schema that may be defined for this specific collection","sourceCodeStart":1045,"sourceCodeEnd":1081,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/dce7939f86fb283e167ad709955abedb7bf23124/src/collection.ts#L1045-L1081","documentation":"Thrown by Collection.aggregate when the pipeline argument is not an array. The method's contract requires Document[] (an array of stage objects); a non-array is a programming error and raises a MongoInvalidArgumentError synchronously before constructing the AggregationCursor.","triggerScenarios":"Fires at src/collection.ts:1063 when `!Array.isArray(pipeline)`. Occurs when a caller passes a single stage object, undefined, a string, or any non-array to aggregate.","commonSituations":"Passing {$match:{}} instead of [{$match:{}}]; passing undefined because pipeline was optional and never defaulted; building stages conditionally and forgetting to wrap; spreading a stage instead of an array.","solutions":["Wrap stages in an array: aggregate([{ $match: {} }]).","Default the parameter: aggregate(pipeline ?? []).","Guard dynamic pipelines with Array.isArray.","Type the variable as Document[] so TS enforces it."],"exampleFix":"// before\ncollection.aggregate({ $match: { status: 'active' } });\n\n// after\ncollection.aggregate([{ $match: { status: 'active' } }]);","handlingStrategy":"validation","validationCode":"const stages = Array.isArray(pipeline) ? pipeline : [pipeline];\ncollection.aggregate(stages);","typeGuard":"function isStageArray(v: unknown): v is Record<string, unknown>[] {\n  return Array.isArray(v) && v.every(s => s != null && typeof s === 'object' && !Array.isArray(s));\n}","tryCatchPattern":null,"preventionTips":["Always pass an array of stage objects to aggregate.","Default optional pipelines: aggregate(pipeline ?? []).","Type pipelines as Document[] so TypeScript enforces the shape."],"tags":["validation","aggregation","typescript","api-misuse"],"backgroundTag":null,"analyzedSha":"dce7939f86fb283e167ad709955abedb7bf23124","analyzedAt":"2026-08-11T04:54:53.215Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}