mongodb/node-mongodb-native · error · MongoInvalidArgumentError
Cannot create a Timeout with a negative duration
Error message
Cannot create a Timeout with a negative duration
What it means
Thrown by the @internal Timeout class constructor when the requested duration is a negative number. Durations of 0 are allowed (used for immediately-rejecting timeouts), but negative durations are nonsensical and rejected up front. It is a MongoInvalidArgumentError.
Source
Thrown at src/timeout.ts:64
if (this.duration === 0) return Infinity;
return this.start + this.duration - Math.trunc(performance.now());
}
get timeElapsed(): number {
return Math.trunc(performance.now()) - this.start;
}
/** Create a new timeout that expires in `duration` ms */
private constructor(
executor: Executor = () => null,
options?: { duration: number; unref?: true; rejection?: Error }
) {
const duration = options?.duration ?? 0;
const unref = !!options?.unref;
const rejection = options?.rejection;
if (duration < 0) {
throw new MongoInvalidArgumentError('Cannot create a Timeout with a negative duration');
}
let reject!: Reject;
super((_, promiseReject) => {
reject = promiseReject;
executor(noop, promiseReject);
});
this.duration = duration;
this.start = Math.trunc(performance.now());
if (rejection == null && this.duration > 0) {
this.id = setTimeout(() => {
this.ended = Math.trunc(performance.now());
this.timedOut = true;
reject(new TimeoutError(`Expired after ${duration}ms`, { duration }));
}, this.duration);View on GitHub (pinned to 3366c21a63)
Solutions
- If you are a driver maintainer, clamp duration to 0 when negative before constructing a Timeout, or use Timeout.reject() to fail fast.
- As a user, ensure timeoutMS values are non-negative and that you are not chaining operations after a timeout has already fired.
- Upgrade the driver: many negative-duration paths were hardened in recent releases; check HISTORY.md.
Example fix
// before (driver-internal pattern)
return new Timeout(undefined, { duration: remaining - slack }); // remaining < slack -> throws
// after
const dur = Math.max(0, remaining - slack);
return dur === 0 ? Timeout.reject(new MongoOperationTimeoutError('expired')) : Timeout.expires(dur); Defensive patterns
Strategy: validation
Validate before calling
// internal: clamp durations before constructing a Timeout
const safeDuration = Math.max(0, requestedDuration);
if (safeDuration === 0) {
return Timeout.reject(new MongoOperationTimeoutError('expired'));
}
return Timeout.expires(safeDuration); Type guard
function isNonNegativeMs(v: unknown): v is number {
return typeof v === 'number' && Number.isFinite(v) && v >= 0;
} Prevention
- Always pass non-negative millisecond values to timeout-related options (timeoutMS, socketTimeoutMS).
- In driver internals, clamp computed durations to 0 before constructing Timeout.
- Treat a computed negative duration as 'expired' and fail fast with Timeout.reject().
When it happens
Trigger: Driver internals computing a remaining time that goes negative (e.g. timeoutMS already exceeded before a Timeout.expires() call) and passing it to the constructor. Not reachable through the public API directly under normal use.
Common situations: CSOT (Client-Side Operation Timeout) edge cases where the deadline has already passed by the time a new Timeout is constructed; bugs in timeout arithmetic; race between timeout expiry and a new operation start.
Related errors
- Timed out
- Unrecognized options
- Unreachable. If you are seeing this error, please file a tic
- KMS request timed out
- Server roundtrip time is greater than the time remaining
AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04).
Data as JSON: /data/errors/d083d37a9d7e3eff.json.
Report an issue: GitHub.