mongodb/node-mongodb-native · error · MongoInvalidArgumentError

An operation cannot be given a timeoutMS setting when…

Error message

An operation cannot be given a timeoutMS setting when inside a withTransaction call that has a timeoutMS setting

What it means

Thrown by resolveOptions() when an operation is executed inside a convenient transaction (session.withTransaction with a timeoutMS / timeoutContext set) AND the per-operation options also specify a timeoutMS. CSOT semantics derive a single deadline from the transaction; nesting a separate timeoutMS is ambiguous and disallowed. Raised as MongoInvalidArgumentError.

Solutions

  1. Remove timeoutMS from the inner operation options; let the transaction's timeoutMS govern the deadline.
  2. If an inner operation needs its own shorter deadline, reconsider whether it belongs in the same transaction.
  3. Set timeoutMS only at the transaction level when using withTransaction.

Example fix

// before
await session.withTransaction(async (session) => {
  await collection.findOne({}, { session, timeoutMS: 1000 });
}, { timeoutMS: 5000 });

// after
await session.withTransaction(async (session) => {
  await collection.findOne({}, { session });
}, { timeoutMS: 5000 });
Defensive patterns

Strategy: validation

Validate before calling

function stripTimeoutMSInTxn(session: import('mongodb').ClientSession, options: any) {
  if (session?.explicit && session?.timeoutContext != null && options?.timeoutMS != null) {
    const { timeoutMS: _omit, ...rest } = options;
    return rest;
  }
  return options;
}

Prevention

When it happens

Trigger: Inside session.withTransaction(async (session) => { collection.findOne({}, { session, timeoutMS: 1000 }) }) where the withTransaction call (or the session) already has a timeoutMS. Passing timeoutMS on both the transaction and its inner operations.

Common situations: Adopting CSOT (Client-Side Operation Timeouts) and setting timeoutMS both at the session/transaction level and on individual operations out of habit. Common when refactoring legacy code that set per-operation timeouts into a transactional context.

Understand the failure class

Related errors


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

Appendix: source

Thrown at src/utils.ts:551

            wtimeout: undefined,
            wtimeoutMS: undefined
          }
        });
      }
      result.writeConcern = writeConcern;
    }
  }

  result.timeoutMS = timeoutMS;

  const readPreference = ReadPreference.fromOptions(options) ?? parent?.readPreference;
  if (readPreference) {
    result.readPreference = readPreference;
  }

  const isConvenientTransaction = session?.explicit && session?.timeoutContext != null;
  if (isConvenientTransaction && options?.timeoutMS != null) {
    throw new MongoInvalidArgumentError(
      'An operation cannot be given a timeoutMS setting when inside a withTransaction call that has a timeoutMS setting'
    );
  }

  return result;
}

export function isSuperset(set: Set<any> | any[], subset: Set<any> | any[]): boolean {
  set = Array.isArray(set) ? new Set(set) : set;
  subset = Array.isArray(subset) ? new Set(subset) : subset;
  for (const elem of subset) {
    if (!set.has(elem)) {
      return false;
    }
  }
  return true;
}

View on GitHub (pinned to dce7939f86)