{"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/3366c21a6311e02f1be91da982f9b93d3cce99a0/src/operations/execute_operation.ts#L129-L165","documentation":"autoConnect (src/operations/execute_operation.ts:147) throws a MongoNotConnectedError when an operation is attempted and the client has been closed (client.s.hasBeenClosed is true). Once close() is called, the client cannot be reused — this guard prevents silent no-ops against a dead topology.","triggerScenarios":"Calling any collection/db operation after client.close() has resolved, or after close() was initiated and an operation races in.","commonSituations":"Application shutdown ordering where close() fires before pending async operations drain, request-scoped clients that close prematurely, or accidental double-use of a client in a graceful-shutdown handler.","solutions":["Ensure all in-flight operations complete before calling client.close().","If you need to resume work, create a new MongoClient rather than reusing the closed one.","Review shutdown hooks to guarantee ordering: drain queries → close client.","Avoid closing the client in middleware that runs per-request."],"exampleFix":"// before\nawait client.close();\nawait collection.insertOne({ a: 1 }); // throws\n\n// after\nawait collection.insertOne({ a: 1 });\nawait client.close();\n// if more work is needed later, create a new client:\n// const client2 = new MongoClient(uri); await client2.connect();","handlingStrategy":"try-catch","validationCode":"function isClientOpen(client: MongoClient): boolean {\n  return !client.s.hasBeenClosed; // internal access; prefer tracking close() in app code\n}\n// better: track lifecycle explicitly in application state","typeGuard":null,"tryCatchPattern":"try {\n  await collection.insertOne(doc);\n} catch (err) {\n  if (err instanceof MongoNotConnectedError) {\n    // client was closed; create a new client to continue\n  } else throw err;\n}","preventionTips":["Call client.close() only after all in-flight operations have drained.","Never reuse a closed MongoClient; create a new instance instead.","Avoid closing clients in per-request middleware."],"tags":["connection","lifecycle","shutdown"],"analyzedSha":"3366c21a6311e02f1be91da982f9b93d3cce99a0","analyzedAt":"2026-08-04T13:40:15.335Z","schemaVersion":2}