mongodb/node-mongodb-native · error · MongoRuntimeError

Unexpected null serverSession for an ended implicit session

Error message

Unexpected null serverSession for an ended implicit session

What it means

The `serverSession` getter throws MongoRuntimeError when `_serverSession` is null, the session is implicit, and `hasEnded` is true. Implicit sessions acquire their ServerSession lazily, so after `endSession()` flips `hasEnded` the getter refuses to mint a new server session.

Solutions

  1. Let the driver manage implicit sessions; do not call endSession on sessions you did not create with `startSession()`.
  2. Close cursors before ending the session they were created with.
  3. When explicitly managing lifecycle, always pair `startSession()` (explicit) with `endSession()`.

Example fix

// before
const cursor = collection.find({}, { session });
await session.endSession();
await cursor.next(); // throws if session was implicit and ended

// after
const docs = await cursor.toArray();
await session.endSession();
Defensive patterns

Strategy: validation

Validate before calling

function ensureAlive(session) {
  if (session.hasEnded) throw new Error('session ended; cannot use');
}

Type guard

function isUsable(session) {
  return !session.hasEnded;
}

Prevention

When it happens

Trigger: An implicit (driver-created) session being used after `endSession()` — for example, an operation on a cursor whose session was already ended, or calling `session.serverSession` on an ended implicit session.

Common situations: Cursors outliving their session; manually ending a session that the driver created implicitly and then running another operation with it; disposing a client while operations are still queued.

Related errors


AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11). Data as JSON: /api/errors/9605308f4cf45512. Report an issue: GitHub.

Appendix: source

Thrown at src/sessions.ts:221

    this.operationTime = undefined;
    this.owner = options.owner;
    this.defaultTransactionOptions = { ...options.defaultTransactionOptions };
    this.transaction = new Transaction();
  }

  /** The server id associated with this session */
  get id(): ServerSessionId | undefined {
    return this.serverSession?.id;
  }

  get serverSession(): ServerSession {
    let serverSession = this._serverSession;
    if (serverSession == null) {
      if (this.explicit) {
        throw new MongoRuntimeError('Unexpected null serverSession for an explicit session');
      }
      if (this.hasEnded) {
        throw new MongoRuntimeError('Unexpected null serverSession for an ended implicit session');
      }
      serverSession = this.sessionPool.acquire();
      this._serverSession = serverSession;
    }
    return serverSession;
  }

  get loadBalanced(): boolean {
    return this.client.topology?.description.type === TopologyType.LoadBalanced;
  }

  /** @internal */
  pin(conn: Connection): void {
    if (this.pinnedConnection) {
      throw TypeError('Cannot pin multiple connections to the same session');
    }

    this.pinnedConnection = conn;

View on GitHub (pinned to dce7939f86)