{"record":{"id":"045d6db349ec898e","repo":"mongodb/node-mongodb-native","slug":"timeoutms-cannot-be-used-with-explain-when-explain-045d6d","errorCode":null,"errorMessage":"timeoutMS cannot be used with explain when explain is specified in findOptions","messagePattern":"timeoutMS cannot be used with explain when explain is specified in findOptions","errorType":"exception","errorClass":"MongoAPIError","httpStatus":null,"severity":"error","filePath":"src/cursor/find_cursor.ts","lineNumber":84,"sourceCode":"\n  override map<T>(transform: (doc: TSchema) => T): FindCursor<T> {\n    return super.map(transform) as FindCursor<T>;\n  }\n\n  /** @internal */\n  async _initialize(session: ClientSession): Promise<InitialCursorResponse> {\n    const options = {\n      ...this.findOptions, // NOTE: order matters here, we may need to refine this\n      ...this.cursorOptions,\n      session,\n      signal: this.signal\n    };\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 findOptions'\n        );\n      }\n    }\n\n    const findOperation = new FindOperation(this.namespace, this.cursorFilter, options);\n\n    const response = await executeOperation(this.client, findOperation, this.timeoutContext);\n\n    // the response is not a cursor when `explain` is enabled\n    this.numReturned = response.batchSize;\n\n    return { server: findOperation.server, session, response };\n  }\n\n  /** @internal */\n  override async getMore(): Promise<CursorResponse> {\n    const numReturned = this.numReturned;","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/dce7939f86fb283e167ad709955abedb7bf23124/src/cursor/find_cursor.ts#L66-L102","documentation":"Thrown by FindCursor._initialize when findOptions enable explain together with timeoutMS and either maxTimeMS or explain.maxTimeMS. Same rule as aggregation: an explain command cannot carry both a server-side maxTimeMS deadline and the client-side timeoutMS deadline. The inner validateExplainTimeoutOptions error is caught and rethrown with this find-specific message.","triggerScenarios":"collection.find({}, { explain: { verbosity: 'queryPlanner', maxTimeMS: 50 }, timeoutMS: 1000 }) then iterating; or cursor.addQueryModifier('$maxTimeMS', 50) plus findOptions.timeoutMS plus explain; or constructing FindCursor directly with explain+maxTimeMS+timeoutMS.","commonSituations":"Migrating query tuning scripts that previously used maxTimeMS to the newer timeoutMS; reusing an options builder across explain and non-explain queries; upgrading the driver to a timeoutMS-enforcing version.","solutions":["Remove maxTimeMS (or explain.maxTimeMS) from findOptions when timeoutMS is set.","Or remove timeoutMS and keep maxTimeMS for the explain run.","Use cursor.explain(verbosity, { timeoutMS }) which resolves the combination correctly."],"exampleFix":"// before\nawait collection.find(\n  {},\n  { explain: { verbosity: 'queryPlanner', maxTimeMS: 50 }, timeoutMS: 1000 }\n).toArray();\n\n// after\nawait collection.find({}).explain('queryPlanner', { timeoutMS: 1000 });","handlingStrategy":"validation","validationCode":"function assertFindExplainTimeout(opts) {\n  if (opts.explain == null) return;\n  const conflict = opts.timeoutMS != null &&\n    (opts.maxTimeMS != null ||\n      (typeof opts.explain === 'object' && opts.explain.maxTimeMS != null));\n  if (conflict) throw new Error('Remove maxTimeMS or timeoutMS before running explain on find.');\n}","typeGuard":null,"tryCatchPattern":"try { await cursor.explain('queryPlanner'); }\ncatch (e) { if (e instanceof MongoAPIError && /timeoutMS cannot be used with explain/.test(e.message)) { /* drop maxTimeMS, retry */ } else throw e; }","preventionTips":["Run explain via cursor.explain(verbosity, { timeoutMS }) rather than embedding explain in find options.","Never set both timeoutMS and maxTimeMS on the same find options object."],"tags":["find","explain","timeout","options-validation"],"backgroundTag":null,"analyzedSha":"dce7939f86fb283e167ad709955abedb7bf23124","analyzedAt":"2026-08-11T04:54:53.215Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}