mongodb/node-mongodb-native · critical · MongoRuntimeError
Unexpected null session. A cursor creating command should…
Error message
Unexpected null session. A cursor creating command should have set this
What it means
Thrown as a MongoRuntimeError from getMore() when cursorSession is null at getMore time. The session is created during cursorInit() (either the user's explicit session or an implicit one with owner=this) and must be reused for every getMore on the same cursor per the cross-driver cursor contract. A null session at getMore time means initialization never ran or the session was cleared (e.g. by a rewind() that ended it) while iteration continued, which is an internal invariant violation. getMore() is @internal.
Solutions
- Report the issue with a reproduction and driver version; this is a driver-internal contract.
- Use only the public iteration API so session creation is handled by cursorInit().
- If providing an explicit session, ensure it remains usable (not ended) for the cursor's lifetime.
- Upgrade to the latest patch release.
Defensive patterns
Strategy: try-catch
Try / catch
try {
await cursor.next();
} catch (err) {
if (err instanceof MongoRuntimeError && /null session/.test(err.message)) {
// internal invariant: recreate the cursor with a fresh implicit session
cursor = collection.find(filter, opts);
} else {
throw err;
}
} Prevention
- Let the driver create and manage implicit sessions; avoid ending an explicit session mid-iteration.
- Do not call the @internal getMore() directly.
- Report suspected driver bugs; keep the driver version current.
When it happens
Trigger: Driver bug where cursorInit() did not assign cursorSession before fetchBatch() ran getMore(); a subclass returns from _initialize() without ensuring a session; session state lost after a partial cleanup triggered by an earlier error.
Common situations: Hitting a driver bug under error paths where cleanup ran but iteration continued; instrumenting session lifecycle; an unhandled rejection in startSession() leaving the cursor without a session.
Related errors
- Unexpected null cursor id. A cursor creating command should…
- Unexpected null selectedServer. A cursor creating command…
- A collection name must be determined before getMore
- A collection name must be determined before killCursors
- Argument for maxTimeMS must be a number
AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11).
Data as JSON: /api/errors/3d89ded6b683147c.
Report an issue: GitHub.
Appendix: source
Thrown at src/cursor/abstract_cursor.ts:872
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,
this.selectedServer,
getMoreOptions
);
return await executeOperation(this.cursorClient, getMoreOperation, this.timeoutContext);
}View on GitHub (pinned to dce7939f86)