{"record":{"id":"4c1f3cd79176ca4f","repo":"mongodb/node-mongodb-native","slug":"client-must-be-connected-before-running-operations","errorCode":null,"errorMessage":"Client must be connected before running operations","messagePattern":"Client must be connected before running operations","errorType":"exception","errorClass":"MongoNotConnectedError","httpStatus":null,"severity":"error","filePath":"src/operations/execute_operation.ts","lineNumber":147,"sourceCode":"      timeoutContext,\n      session,\n      readPreference\n    });\n  } finally {\n    if (session?.owner != null && session.owner === owner) {\n      await session.endSession();\n    }\n  }\n}\n\n/**\n * Connects a client if it has not yet been connected\n * @internal\n */\nexport async function autoConnect(client: MongoClient): Promise<Topology> {\n  if (client.topology == null) {\n    if (client.s.hasBeenClosed) {\n      throw new MongoNotConnectedError('Client must be connected before running operations');\n    }\n    client.s.options.__skipPingOnConnect = true;\n    try {\n      await client.connect();\n      if (client.topology == null) {\n        throw new MongoRuntimeError(\n          'client.connect did not create a topology but also did not throw'\n        );\n      }\n      return client.topology;\n    } finally {\n      delete client.s.options.__skipPingOnConnect;\n    }\n  }\n  return client.topology;\n}\n\n/** @internal */","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/dce7939f86fb283e167ad709955abedb7bf23124/src/operations/execute_operation.ts#L129-L165","documentation":"Thrown when an operation needs to auto-connect the client but the client has already been closed (s.hasBeenClosed is true). Once MongoClient.close() runs, the client is permanently unusable; any further operation is rejected rather than silently reconnecting.","triggerScenarios":"Calling collection.find(), insertOne(), etc. after awaiting client.close(); sharing a client across a worker pool where one branch closes it while another still issues queries; app shutdown sequences that close the client before draining in-flight requests.","commonSituations":"Process teardown that closes the DB before async work finishes; test afterEach hooks that close a shared client while a test still has pending queries; refactoring a singleton client into a per-request lifecycle.","solutions":["Defer client.close() until all in-flight operations have completed (e.g. await Promise.allSettled(pending)).","Use a single long-lived MongoClient for the process lifetime; do not close and recreate it per request.","If you need a fresh client, create a new MongoClient rather than reusing a closed one."],"exampleFix":"// before\nawait client.close();\nawait collection.insertOne({}); // throws\n\n// after\nawait collection.insertOne({});\nawait client.close();","handlingStrategy":"try-catch","validationCode":"if (client.s.hasBeenClosed) {\n  throw new Error('MongoClient has been closed; create a new client');\n}\nawait collection.findOne({});","typeGuard":null,"tryCatchPattern":"try {\n  await collection.findOne({});\n} catch (e) {\n  if (/Client must be connected/.test(e.message)) {\n    // create a fresh MongoClient and reconnect\n    client = new MongoClient(uri); await client.connect();\n  }\n}","preventionTips":["Use one long-lived MongoClient per process; close only during shutdown after in-flight work drains.","Await Promise.allSettled on pending operations before calling client.close()."],"tags":["lifecycle","connection","api-misuse"],"backgroundTag":null,"analyzedSha":"dce7939f86fb283e167ad709955abedb7bf23124","analyzedAt":"2026-08-11T04:54:53.215Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}