mongodb/node-mongodb-native · error · MongoRuntimeError

Unexpected null session. A cursor creating command should ha

Error message

Unexpected null session. A cursor creating command should have set this

What it means

A defensive invariant in RunCommandCursor.getMore() that asserts a ClientSession exists. A session is allocated during cursor initialization (the first _read/next), so reaching getMore without one indicates the cursor lifecycle was violated (reused after close, manipulated out of order) or a driver-internal bug. It is a MongoRuntimeError, not user input.

Source

Thrown at src/cursor/run_command_cursor.ts:164

    const operation = new RunCursorCommandOperation(this.db.s.namespace, this.command, {
      ...this.cursorOptions,
      session: session,
      readPreference: this.cursorOptions.readPreference
    });

    const response = await executeOperation(this.client, operation, this.timeoutContext);

    return {
      server: operation.server,
      session,
      response
    };
  }

  /** @internal */
  override async getMore(): Promise<CursorResponse> {
    if (!this.session) {
      throw new MongoRuntimeError(
        'Unexpected null session. A cursor creating command should have set this'
      );
    }

    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
    const getMoreOperation = new GetMoreOperation(this.namespace, this.id!, this.server!, {
      ...this.cursorOptions,
      session: this.session,
      ...this.getMoreOptions
    });

    return await executeOperation(this.client, getMoreOperation, this.timeoutContext);
  }
}

View on GitHub (pinned to 3366c21a63)

Solutions

  1. Do not reuse a RunCommandCursor after it has been closed, completed, or errored
  2. Create a fresh RunCommandCursor for each independent iteration
  3. Avoid concurrent iteration of a single cursor instance
  4. If reproducible on the latest driver version, file a bug with the command and exact lifecycle
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await cursor.next();
} catch (err) {
  if (err instanceof MongoRuntimeError && /null session/i.test(err.message)) {
    // cursor lifecycle is broken; discard and recreate
    cursor = db.runCursorCommand(cmd);
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: Calling getMore after the cursor was closed/killed, reusing a cursor after it errored or completed, concurrent iteration of the same cursor, or a driver regression.

Common situations: Race conditions; manual cursor cleanup; re-entering an async iterator after it threw; driver version mismatches.

Related errors


AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04). Data as JSON: /data/errors/b02f5e749d2c6261.json. Report an issue: GitHub.