mongodb/node-mongodb-native · critical · MongoRuntimeError
Cursor must be constructed with MongoClient
Error message
Cursor must be constructed with MongoClient
What it means
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.
Source
Thrown at src/cursor/abstract_cursor.ts:262
/** @event */
static readonly CLOSE = 'close' as const;
/** @internal */
protected deserializationOptions: OnDemandDocumentDeserializeOptions;
protected signal: AbortSignal | undefined;
private abortListener: Disposable | undefined;
/** @internal */
protected constructor(
client: MongoClient,
namespace: MongoDBNamespace,
options: AbstractCursorOptions & Abortable = {}
) {
super();
this.on('error', noop);
if (!client.s.isMongoClient) {
throw new MongoRuntimeError('Cursor must be constructed with MongoClient');
}
this.cursorClient = client;
this.cursorNamespace = namespace;
this.cursorId = null;
this.initialized = false;
this.isClosed = false;
this.isKilled = false;
this.cursorOptions = {
readPreference:
options.readPreference && options.readPreference instanceof ReadPreference
? options.readPreference
: ReadPreference.primary,
...pluckBSONSerializeOptions(options),
timeoutMS: options?.timeoutContext?.csotEnabled()
? options.timeoutContext.timeoutMS
: options.timeoutMS,
tailable: options.tailable,
awaitData: options.awaitDataView on GitHub (pinned to 3366c21a63)
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.
Example fix
// before
cursor = new FindCursor(collection, ns, {}); // wrong first arg
// after
cursor = collection.find({}); // let the driver build the cursor Defensive patterns
Strategy: type-guard
Validate before calling
import { MongoClient } from 'mongodb';
function isRealClient(v) { return v instanceof MongoClient; } Type guard
function isMongoClient(v): v is MongoClient { return v instanceof MongoClient && !!v?.s?.isMongoClient; } Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Argument "iterator" must be a function
- Flag ${flag} is not one of ${CURSOR_FLAGS}
- Tailable cursor does not support batchSize
- Server ended moreToCome unexpectedly
- Cursor document did not contain a batch
AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04).
Data as JSON: /data/errors/a04ac77821734d00.json.
Report an issue: GitHub.