{"id":"a04ac77821734d00","repo":"mongodb/node-mongodb-native","slug":"cursor-must-be-constructed-with-mongoclient","errorCode":null,"errorMessage":"Cursor must be constructed with MongoClient","messagePattern":"Cursor must be constructed with MongoClient","errorType":"exception","errorClass":"MongoRuntimeError","httpStatus":null,"severity":"critical","filePath":"src/cursor/abstract_cursor.ts","lineNumber":262,"sourceCode":"  /** @event */\n  static readonly CLOSE = 'close' as const;\n\n  /** @internal */\n  protected deserializationOptions: OnDemandDocumentDeserializeOptions;\n  protected signal: AbortSignal | undefined;\n  private abortListener: Disposable | undefined;\n\n  /** @internal */\n  protected constructor(\n    client: MongoClient,\n    namespace: MongoDBNamespace,\n    options: AbstractCursorOptions & Abortable = {}\n  ) {\n    super();\n    this.on('error', noop);\n\n    if (!client.s.isMongoClient) {\n      throw new MongoRuntimeError('Cursor must be constructed with MongoClient');\n    }\n    this.cursorClient = client;\n    this.cursorNamespace = namespace;\n    this.cursorId = null;\n    this.initialized = false;\n    this.isClosed = false;\n    this.isKilled = false;\n    this.cursorOptions = {\n      readPreference:\n        options.readPreference && options.readPreference instanceof ReadPreference\n          ? options.readPreference\n          : ReadPreference.primary,\n      ...pluckBSONSerializeOptions(options),\n      timeoutMS: options?.timeoutContext?.csotEnabled()\n        ? options.timeoutContext.timeoutMS\n        : options.timeoutMS,\n      tailable: options.tailable,\n      awaitData: options.awaitData","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/3366c21a6311e02f1be91da982f9b93d3cce99a0/src/cursor/abstract_cursor.ts#L244-L280","documentation":"Thrown by the AbstractCursor constructor when the supplied client is not a genuine MongoClient instance (the internal isMongoClient flag is false). Cursors must be backed by a real client because they depend on its session pool, topology, and SDAM state.","triggerScenarios":"Constructing a cursor with a plain object, a mock, a Db/Collection instance mistaken for a client, a client from an incompatible driver version, or a client whose symbol was stripped (e.g. by serialization/structuredClone).","commonSituations":"Test code passing a stub client; refactoring that passes `collection` or `db` where `client` was expected; using two installed copies of the driver where instanceof checks fail across module instances.","solutions":["Obtain the client via MongoClient.connect() or new MongoClient(uri).connect() and pass that exact instance.","In tests, mock at the operation/server layer rather than fabricating a cursor directly.","If you have a Db/Collection, use collection.find() which internally forwards the correct client."],"exampleFix":"// before\ncursor = new FindCursor(collection, ns, {}); // wrong first arg\n// after\ncursor = collection.find({}); // let the driver build the cursor","handlingStrategy":"type-guard","validationCode":"import { MongoClient } from 'mongodb';\nfunction isRealClient(v) { return v instanceof MongoClient; }","typeGuard":"function isMongoClient(v): v is MongoClient { return v instanceof MongoClient && !!v?.s?.isMongoClient; }","tryCatchPattern":null,"preventionTips":["Never construct AbstractCursor subclasses directly — always go through collection.find()/aggregate().","Ensure a single driver installation to avoid cross-module instanceof failures.","Mock at the server/operation layer in tests, not at the cursor constructor."],"tags":["cursor","internal-api","misuse"],"analyzedSha":"3366c21a6311e02f1be91da982f9b93d3cce99a0","analyzedAt":"2026-08-04T13:40:15.335Z","schemaVersion":2}