mongodb/node-mongodb-native · error · MongoRuntimeError
Unexpected null selectedServer. A cursor creating command sh
Error message
Unexpected null selectedServer. A cursor creating command should have set this
What it means
Thrown by AbstractCursor.getMore() when selectedServer is null while dispatching a getMore. selectedServer is populated during cursorInit() from the _initialize() result (abstract_cursor.ts:915) and is required to route the getMore to the correct server. Like the null cursorId check, this should be unreachable through public iteration APIs because cursorInit() runs before getMore() in fetchBatch().
Source
Thrown at src/cursor/abstract_cursor.ts:866
/**
* Returns a new uninitialized copy of this cursor, with options matching those that have been set on the current instance
*/
abstract clone(): AbstractCursor<TSchema>;
/** @internal */
protected abstract _initialize(
session: ClientSession | undefined
): Promise<InitialCursorResponse>;
/** @internal */
async getMore(): Promise<CursorResponse> {
if (this.cursorId == null) {
throw new MongoRuntimeError(
'Unexpected null cursor id. A cursor creating command should have set this'
);
}
if (this.selectedServer == null) {
throw new MongoRuntimeError(
'Unexpected null selectedServer. A cursor creating command should have set this'
);
}
if (this.cursorSession == null) {
throw new MongoRuntimeError(
'Unexpected null session. A cursor creating command should have set this'
);
}
const getMoreOptions = {
...this.cursorOptions,
session: this.cursorSession,
batchSize: this.cursorOptions.batchSize
};
const getMoreOperation = new GetMoreOperation(
this.cursorNamespace,
this.cursorId,View on GitHub (pinned to 3366c21a63)
Solutions
- Ensure any custom _initialize() returns a real server object (e.g. AggregateOperation/FindOperation .server after executeOperation)
- Do not invoke the internal getMore() directly; iterate via next()/for-await/toArray()
- Verify you are not reusing a cursor instance whose server reference was cleared by cleanup()
Example fix
// before
async _initialize(session) {
const resp = await executeOperation(this.client, op);
return { response: resp, session }; // missing server
}
// after
async _initialize(session) {
const resp = await executeOperation(this.client, op);
return { response: resp, server: op.server, session };
} Defensive patterns
Strategy: validation
Validate before calling
// Validate custom _initialize output before returning it
async _initialize(session) {
const response = await executeOperation(this.client, op);
if (!op.server) throw new Error('no server selected');
return { response, server: op.server, session };
} Prevention
- Ensure custom _initialize() returns the server from the executed operation
- Iterate via public next()/toArray() so cursorInit() runs first
- Avoid direct calls to internal getMore()
When it happens
Trigger: A custom _initialize() implementation that returns an InitialCursorResponse without a server field, or direct invocation of the @internal getMore() before the cursor has been initialized. Also theoretically possible if server selection was somehow stripped after init.
Common situations: Custom cursor subclasses, test harnesses that stub _initialize() incompletely, or integration with mock libraries that replace the init response object.
Related errors
- Unexpected null cursor id. A cursor creating command should
- Unexpected null session. A cursor creating command should ha
- Unexpected null session. A cursor creating command should ha
- Unable to iterate cursor with no id
- A collection name must be determined before getMore
AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04).
Data as JSON: /data/errors/9cab7e9773bf0ebd.json.
Report an issue: GitHub.