mongodb/node-mongodb-native · error · MongoExpiredSessionError

Use of expired sessions is not permitted

Error message

Use of expired sessions is not permitted

What it means

Thrown when an operation is executed with a ClientSession that has already been ended (session.hasEnded is true). Sessions are single-use: once endSession() runs (explicitly or via withSession's finally block), the session cannot be reused for further operations.

Solutions

  1. Do not escape the session from withSession — perform all work inside the callback.
  2. If managing sessions manually, never reuse after endSession(); create a new session with startSession() instead.
  3. Check session.hasEnded before passing to an operation as a defensive guard.

Example fix

// before
let saved;
await client.withSession(session => { saved = session; });
await collection.insertOne({}, { session: saved }); // session has ended

// after
await client.withSession(async session => {
  await collection.insertOne({}, { session });
});
Defensive patterns

Strategy: validation

Validate before calling

if (session.hasEnded) {
  throw new Error('Cannot reuse an ended session');
}
await collection.findOne({}, { session });

Type guard

const isLiveSession = (s: { hasEnded?: boolean }): boolean =>
  s != null && s.hasEnded !== true;

Try / catch

try {
  await collection.findOne({}, { session });
} catch (e) {
  if (/expired sessions/.test(e.message)) {
    session = client.startSession();
    // retry once with a fresh session
  }
}

Prevention

When it happens

Trigger: Keeping a reference to a session from inside client.withSession and using it after the callback returns; calling session.endSession() manually and then passing the same session to another operation; caching sessions across requests.

Common situations: Web handlers that store the session on the request object and reuse it after the response; helpers that call endSession too early in a pipeline; misusing withSession by escaping the session via a closure.

Related errors


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

Appendix: source

Thrown at src/operations/execute_operation.ts:88

    // TODO(NODE-3483): Extend MongoRuntimeError
    throw new MongoRuntimeError('This method requires a valid operation instance');
  }

  const topology =
    client.topology == null
      ? await abortable(autoConnect(client), operation.options)
      : client.topology;

  // The driver sessions spec mandates that we implicitly create sessions for operations
  // that are not explicitly provided with a session.
  let session = operation.session;
  let owner: symbol | undefined;

  if (session == null) {
    owner = Symbol();
    session = client.startSession({ owner, explicit: false });
  } else if (session.hasEnded) {
    throw new MongoExpiredSessionError('Use of expired sessions is not permitted');
  } else if (
    session.snapshotEnabled &&
    maxWireVersion(topology) < MIN_SUPPORTED_SNAPSHOT_READS_WIRE_VERSION
  ) {
    throw new MongoCompatibilityError('Snapshot reads require MongoDB 5.0 or later');
  } else if (session.client !== client) {
    throw new MongoInvalidArgumentError('ClientSession must be from the same MongoClient');
  }

  operation.session ??= session;

  const readPreference = operation.readPreference ?? ReadPreference.primary;
  const inTransaction = !!session?.inTransaction();

  const hasReadAspect = operation.hasAspect(Aspect.READ_OPERATION);

  if (
    inTransaction &&

View on GitHub (pinned to dce7939f86)