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

  1. Report the issue with a reproduction and driver version; this is a driver-internal contract.
  2. Use only the public iteration API so session creation is handled by cursorInit().
  3. If providing an explicit session, ensure it remains usable (not ended) for the cursor's lifetime.
  4. 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

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


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)