{"id":"da85d8bb7f9692a5","repo":"mongodb/node-mongodb-native","slug":"cannot-use-maxtimems-with-timeoutms-for-explain-co","errorCode":null,"errorMessage":"Cannot use maxTimeMS with timeoutMS for explain commands.","messagePattern":"Cannot use maxTimeMS with timeoutMS for explain commands\\.","errorType":"exception","errorClass":"MongoAPIError","httpStatus":null,"severity":"error","filePath":"src/explain.ts","lineNumber":96,"sourceCode":"    this.maxTimeMS = maxTimeMS;\n  }\n\n  static fromOptions({ explain }: ExplainOptions = {}): Explain | undefined {\n    if (explain == null) return;\n\n    if (typeof explain === 'boolean' || typeof explain === 'string') {\n      return new Explain(explain);\n    }\n\n    const { verbosity, maxTimeMS } = explain;\n    return new Explain(verbosity, maxTimeMS);\n  }\n}\n\nexport function validateExplainTimeoutOptions(options: Document, explain?: Explain) {\n  const { maxTimeMS, timeoutMS } = options;\n  if (timeoutMS != null && (maxTimeMS != null || explain?.maxTimeMS != null)) {\n    throw new MongoAPIError('Cannot use maxTimeMS with timeoutMS for explain commands.');\n  }\n}\n\n/**\n * Applies an explain to a given command.\n * @internal\n *\n * @param command - the command on which to apply the explain\n * @param options - the options containing the explain verbosity\n */\nexport function decorateWithExplain(\n  command: Document,\n  explain: Explain\n): {\n  explain: Document;\n  verbosity: ExplainVerbosity;\n  maxTimeMS?: number;\n} {","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/3366c21a6311e02f1be91da982f9b93d3cce99a0/src/explain.ts#L78-L114","documentation":"Under Client-Side Operation Timeout (CSOT, the timeoutMS option) combining maxTimeMS with timeoutMS on explain commands is ambiguous and explicitly forbidden by validateExplainTimeoutOptions(). Pick a single timeout mechanism for explain.","triggerScenarios":"collection.find(filter, { explain: { verbosity: 'queryPlanner', maxTimeMS: 1000 }, timeoutMS: 5000 }), or setting maxTimeMS on the command while timeoutMS is configured on the client/cursor.","commonSituations":"Migrating to CSOT while leaving legacy maxTimeMS in place; copy-pasting explain options into a timeoutMS-enabled codebase.","solutions":["Remove maxTimeMS from the explain options and rely on timeoutMS alone","Or remove timeoutMS for this operation and keep maxTimeMS","Standardize the project on timeoutMS and audit for leftover maxTimeMS"],"exampleFix":"// before\ncollection.find(f, { explain: { verbosity: 'queryPlanner', maxTimeMS: 1000 }, timeoutMS: 5000 });\n// after\ncollection.find(f, { explain: { verbosity: 'queryPlanner' }, timeoutMS: 5000 });","handlingStrategy":"validation","validationCode":"function assertExplainTimeout(options) {\n  const hasMaxTime = options?.explain && typeof options.explain === 'object'\n    && options.explain.maxTimeMS != null;\n  if (options?.timeoutMS != null && (options?.maxTimeMS != null || hasMaxTime)) {\n    throw new Error('Pick either maxTimeMS or timeoutMS for explain, not both');\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Adopt timeoutMS project-wide and remove legacy maxTimeMS","Never mix the two on explain-bearing operations","Lint options objects for the conflict"],"tags":["explain","timeout","csot","config"],"analyzedSha":"3366c21a6311e02f1be91da982f9b93d3cce99a0","analyzedAt":"2026-08-04T13:40:15.335Z","schemaVersion":2}