{"id":"d4d3410387a0961f","repo":"mongodb/node-mongodb-native","slug":"server-reported-a-timeout-error","errorCode":null,"errorMessage":"Server reported a timeout error","messagePattern":"Server reported a timeout error","errorType":"exception","errorClass":"MongoOperationTimeoutError","httpStatus":null,"severity":"error","filePath":"src/cmap/connection.ts","lineNumber":559,"sourceCode":"    let document: MongoDBResponse | undefined = undefined;\n    /** Cached result of a toObject call */\n    let object: Document | undefined = undefined;\n    try {\n      this.throwIfAborted();\n      for await (document of this.sendWire(message, options, responseType)) {\n        object = undefined;\n        if (options.session != null) {\n          updateSessionFromResponse(options.session, document);\n        }\n\n        if (document.$clusterTime) {\n          this.clusterTime = document.$clusterTime;\n          this.emit(Connection.CLUSTER_TIME_RECEIVED, document.$clusterTime);\n        }\n\n        if (document.ok === 0) {\n          if (options.timeoutContext?.csotEnabled() && document.isMaxTimeExpiredError) {\n            throw new MongoOperationTimeoutError('Server reported a timeout error', {\n              cause: new MongoServerError((object ??= document.toObject(bsonOptions)))\n            });\n          }\n          throw new MongoServerError((object ??= document.toObject(bsonOptions)));\n        }\n\n        if (this.shouldEmitAndLogCommand) {\n          this.emitAndLogCommand(\n            this.monitorCommands,\n            Connection.COMMAND_SUCCEEDED,\n            message.databaseName,\n            this.established,\n            new CommandSucceededEvent(\n              this,\n              message,\n              message.moreToCome ? { ok: 1 } : (object ??= document.toObject(bsonOptions)),\n              started,\n              this.description.serverConnectionId","sourceCodeStart":541,"sourceCodeEnd":577,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/3366c21a6311e02f1be91da982f9b93d3cce99a0/src/cmap/connection.ts#L541-L577","documentation":"Thrown in sendCommand (src/cmap/connection.ts:557-562) when the server returned ok === 0, the response is flagged as a maxTime-expired error, and CSOT (timeoutMS) is enabled. The driver wraps the underlying MongoServerError as the cause of a MongoOperationTimeoutError so callers see a timeout-semantic error while preserving server diagnostics.","triggerScenarios":"Any command (query, aggregate, write) where the server's own maxTimeMS or the driver-translated timeoutMS elapsed server-side and the server replied with a maxTimeMSExpired error code. Common with large aggregations, unindexed queries, or long-running writes under a tight timeoutMS.","commonSituations":"Setting timeoutMS on an aggregation over a large collection without supporting indexes; cursor.getMore() exceeding the budget; write operations with wtimeout/journal concerns compounded by timeoutMS; slow queries against a loaded server.","solutions":["Increase timeoutMS for the specific operation or remove it to use the server default.","Add indexes or optimize the query/aggregation pipeline to run within the budget.","Use $maxTimeMS in the pipeline or cursor.maxTimeMS() to make the limit explicit and tunable.","Offload long-running analytics to a dedicated read node with a larger budget."],"exampleFix":"// before\nawait coll.aggregate(bigPipeline, { timeoutMS: 100 }).toArray();\n\n// after\nawait coll.createIndexes([{ key: { field: 1 } }]);\nawait coll.aggregate(bigPipeline, { timeoutMS: 5000 }).toArray();","handlingStrategy":"retry","validationCode":"function budgetForQuery(timeoutMS: number, estimatedWorkMS: number) {\n  if (timeoutMS < estimatedWorkMS) {\n    throw new Error(`timeoutMS ${timeoutMS} < estimated server work ${estimatedWorkMS}ms`);\n  }\n}","typeGuard":"import { MongoOperationTimeoutError } from 'mongodb';\nfunction isServerMaxTimeExpired(e: unknown): e is MongoOperationTimeoutError {\n  return e instanceof MongoOperationTimeoutError &&\n    /Server reported a timeout/.test(e.message);\n}","tryCatchPattern":"import { MongoOperationTimeoutError } from 'mongodb';\nasync function findWithBackoff(coll: any, q: any, timeoutMS = 1000) {\n  for (;;) {\n    try { return await coll.find(q, { timeoutMS }).toArray(); }\n    catch (e) {\n      if (e instanceof MongoOperationTimeoutError && timeoutMS < 10000) {\n        timeoutMS *= 2; continue;\n      }\n      throw e;\n    }\n  }\n}","preventionTips":["Add indexes for query shapes that hit maxTimeMS limits.","Set timeoutMS per operation based on expected workload, not globally tiny.","Use explain() to confirm the query is using an index before tightening timeouts."],"tags":["timeout","csot","query","aggregation"],"analyzedSha":"3366c21a6311e02f1be91da982f9b93d3cce99a0","analyzedAt":"2026-08-04T13:40:15.335Z","schemaVersion":2}