mongodb/node-mongodb-native · error · MongoOperationTimeoutError
Expired after ${this.timeoutMS}ms
Error message
Expired after ${this.timeoutMS}ms What it means
Thrown by the @internal CSOTTimeoutContext.getRemainingTimeMSOrThrow() when remainingTimeMS <= 0, i.e. the CSOT deadline has passed. The message includes the original timeoutMS. It surfaces as a MongoOperationTimeoutError and is the primary way CSOT-enforced operations fail once their budget is exhausted.
Source
Thrown at src/timeout.ts:314
this.minRoundTripTime = 0;
this._serverSelectionTimeout?.clear();
this._connectionCheckoutTimeout?.clear();
}
clear(): void {
this._serverSelectionTimeout?.clear();
this._connectionCheckoutTimeout?.clear();
}
/**
* @internal
* Throws a MongoOperationTimeoutError if the context has expired.
* If the context has not expired, returns the `remainingTimeMS`
**/
getRemainingTimeMSOrThrow(message?: string): number {
const { remainingTimeMS } = this;
if (remainingTimeMS <= 0)
throw new MongoOperationTimeoutError(message ?? `Expired after ${this.timeoutMS}ms`);
return remainingTimeMS;
}
/**
* @internal
* This method is intended to be used in situations where concurrent operation are on the same deadline, but cannot share a single `TimeoutContext` instance.
* Returns a new instance of `CSOTTimeoutContext` constructed with identical options, but setting the `start` property to `this.start`.
*/
clone(): CSOTTimeoutContext {
const timeoutContext = new CSOTTimeoutContext({
timeoutMS: this.timeoutMS,
serverSelectionTimeoutMS: this.serverSelectionTimeoutMS
});
timeoutContext.start = this.start;
return timeoutContext;
}
override refreshed(): CSOTTimeoutContext {View on GitHub (pinned to 3366c21a63)
Solutions
- Increase timeoutMS to match realistic operation latency.
- Optimize the operation (indexes, $project to reduce payload, narrower filters) to fit the budget.
- For transactions, size timeoutMS to the whole transaction, not a single op, since withTransaction shares one deadline.
- Scale the cluster (more CPU/replicas) if the workload legitimately needs more time.
Example fix
// before
await coll.aggregate([ /* heavy pipeline */ ], { timeoutMS: 1000 }).toArray(); // throws Expired after 1000ms
// after
await coll.aggregate([ /* heavy pipeline */ ], { timeoutMS: 60_000 }).toArray(); Defensive patterns
Strategy: retry
Validate before calling
// size timeoutMS to realistic latency; budget the whole transaction
const timeoutMS = Math.max(30_000, estimatedMs * 3);
await coll.find({}, { timeoutMS }).toArray(); Type guard
import { MongoOperationTimeoutError } from 'mongodb';
function isOperationTimeout(e: unknown): e is MongoOperationTimeoutError {
return e instanceof MongoOperationTimeoutError;
} Try / catch
try {
await coll.aggregate(pipeline, { timeoutMS: 5_000 }).toArray();
} catch (e) {
if (isOperationTimeout(e)) {
// retry with a larger budget or surface 'query too slow for deadline'
await coll.aggregate(pipeline, { timeoutMS: 60_000 }).toArray();
} else throw e;
} Prevention
- Set timeoutMS from measured latency, with headroom (e.g. 3x p99).
- Index and $project to keep operations inside the budget.
- For withTransaction, allocate timeoutMS across all ops in the callback.
When it happens
Trigger: Any operation running under timeoutMS (CSOT) whose wall-clock budget runs out before completion: slow queries, long server selection, slow connection checkout, or chained operations sharing one deadline.
Common situations: Setting an aggressive timeoutMS on heavy aggregations/queries; network latency or cluster load pushing operations past the budget; sequential operations inside withTransaction({ timeoutMS }) exhausting the shared budget.
Related errors
- Timed out
- KMS request timed out
- Server roundtrip time is greater than the time remaining
- Server reported a timeout error
- Timed out during connection checkout
AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04).
Data as JSON: /data/errors/c380e09882d6be7f.json.
Report an issue: GitHub.