{"id":"c78c41f26535b713","repo":"mongodb/node-mongodb-native","slug":"timeoutms-cannot-be-used-with-explain-when-explain","errorCode":null,"errorMessage":"timeoutMS cannot be used with explain when explain is specified in aggregateOptions","messagePattern":"timeoutMS cannot be used with explain when explain is specified in aggregateOptions","errorType":"exception","errorClass":"MongoAPIError","httpStatus":null,"severity":"error","filePath":"src/cursor/aggregation_cursor.ts","lineNumber":84,"sourceCode":"  }\n\n  override map<T>(transform: (doc: TSchema) => T): AggregationCursor<T> {\n    return super.map(transform) as AggregationCursor<T>;\n  }\n\n  /** @internal */\n  async _initialize(session: ClientSession): Promise<InitialCursorResponse> {\n    const options = {\n      ...this.aggregateOptions,\n      ...this.cursorOptions,\n      session,\n      signal: this.signal\n    };\n    if (options.explain) {\n      try {\n        validateExplainTimeoutOptions(options, Explain.fromOptions(options));\n      } catch {\n        throw new MongoAPIError(\n          'timeoutMS cannot be used with explain when explain is specified in aggregateOptions'\n        );\n      }\n    }\n\n    const aggregateOperation = new AggregateOperation(this.namespace, this.pipeline, options);\n\n    const response = await executeOperation(this.client, aggregateOperation, this.timeoutContext);\n\n    return { server: aggregateOperation.server, session, response };\n  }\n\n  /** Execute the explain for the cursor */\n  async explain(): Promise<Document>;\n  async explain(verbosity: ExplainVerbosityLike | ExplainCommandOptions): Promise<Document>;\n  async explain(options: { timeoutMS?: number }): Promise<Document>;\n  async explain(\n    verbosity: ExplainVerbosityLike | ExplainCommandOptions,","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/3366c21a6311e02f1be91da982f9b93d3cce99a0/src/cursor/aggregation_cursor.ts#L66-L102","documentation":"Thrown by AggregationCursor._initialize() (MongoAPIError) when explain is present in aggregateOptions and the explain/timeout option combination is invalid — specifically when validateExplainTimeoutOptions() detects timeoutMS used together with maxTimeMS (or explain.maxTimeMS). The driver forbids combining the modern timeoutMS with the legacy maxTimeMS on an explained aggregate command.","triggerScenarios":"collection.aggregate(pipeline, { explain: true, timeoutMS: N, maxTimeMS: M }) or explain.maxTimeMS set. Triggered lazily when the cursor initializes (first next()/toArray()).","commonSituations":"Migrating from maxTimeMS to timeoutMS while leaving explain/maxTimeMS in a shared options object; passing a generic query-options preset to both explained and non-explained queries.","solutions":["Use EITHER timeoutMS OR maxTimeMS, not both, on explained aggregations","Drop maxTimeMS/explain.maxTimeMS from the options when using timeoutMS","Call cursor.explain() instead of putting explain in aggregateOptions — explain() manages timeout separately"],"exampleFix":"// before\ncoll.aggregate(p, { explain: true, timeoutMS: 1000, maxTimeMS: 500 });\n// after\ncoll.aggregate(p, { explain: true, maxTimeMS: 500 }); // or just timeoutMS","handlingStrategy":"validation","validationCode":"function cleanExplainTimeout(opts) {\n  if (opts.explain && opts.timeoutMS != null) {\n    const { maxTimeMS, explain, ...rest } = opts;\n    return { ...rest, explain: typeof explain === 'object' ? { ...explain, maxTimeMS: undefined } : explain };\n  }\n  return opts;\n}\ncoll.aggregate(p, cleanExplainTimeout(opts));","typeGuard":"const hasConflictingTimeout = (o) => o.explain != null && o.timeoutMS != null && (o.maxTimeMS != null || o.explain?.maxTimeMS != null);","tryCatchPattern":null,"preventionTips":["Use either timeoutMS or maxTimeMS, never both, on explained aggregations","Prefer cursor.explain() over putting explain in aggregateOptions","Sanitize shared options objects before passing to explained queries"],"tags":["aggregation","explain","timeout","timeoutms","maxtimems"],"analyzedSha":"3366c21a6311e02f1be91da982f9b93d3cce99a0","analyzedAt":"2026-08-04T13:40:15.335Z","schemaVersion":2}