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
- Remove timeoutMS from the inner operation options; let the transaction's timeoutMS govern the deadline.
- If an inner operation needs its own shorter deadline, reconsider whether it belongs in the same transaction.
- 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
- Set timeoutMS only at the transaction level when using withTransaction; do not pass it on inner operations.
- When refactoring code into a transaction, audit and remove per-operation timeoutMS settings.
- Document the single-deadline CSOT model for your team to avoid conflicting timeouts.
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
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Cannot create a Timeout with a negative duration
- Cannot set timeoutMode without setting timeoutMS
- Cannot specify maxAwaitTimeMS >= timeoutMS for a tailable…
- Cannot use maxTimeMS with timeoutMS for explain commands.
- Expired after ms
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)