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 constructor when the duration option is a negative number. Timeouts represent a finite future deadline, so a negative duration is logically invalid. The check guards every internal Timeout.expires() call that derives durations from user-supplied timeoutMS, socketTimeoutMS, serverSelectionTimeoutMS, etc.
Solutions
- Ensure all timeout options (timeoutMS, socketTimeoutMS, serverSelectionTimeoutMS, waitQueueTimeoutMS) are non-negative integers.
- If timeouts come from env vars or config, validate them with a parseUnsignedInteger-style guard before passing to the client.
- Use 0 or omit the option to disable a timeout rather than passing a negative number.
Example fix
// before
new MongoClient(uri, { serverSelectionTimeoutMS: -1 });
// after
new MongoClient(uri, { serverSelectionTimeoutMS: 5000 }); Defensive patterns
Strategy: validation
Validate before calling
function resolveTimeout(name: string, value: unknown): number | undefined {
if (value == null) return undefined;
const n = typeof value === 'number' ? value : Number(value);
if (!Number.isFinite(n) || n < 0) throw new Error(`Invalid ${name}: ${value}`);
return Math.trunc(n);
}
new MongoClient(uri, { serverSelectionTimeoutMS: resolveTimeout('serverSelectionTimeoutMS', process.env.SELECT_TIMEOUT) }); Type guard
function isNonNegativeNumber(v: unknown): v is number {
return typeof v === 'number' && Number.isFinite(v) && v >= 0;
} Try / catch
try {
await client.connect();
} catch (e) {
if (e instanceof MongoInvalidArgumentError && /negative duration/.test(e.message)) {
// fix config and retry with valid timeouts
} else throw e;
} Prevention
- Validate all timeout options from env/config with a non-negative-number guard before constructing the client.
- Use 0 or omit a timeout to disable it instead of passing -1.
- Centralize connection-string/option construction in one validated helper.
When it happens
Trigger: Setting a negative value for timeoutMS, socketTimeoutMS, waitQueueTimeoutMS, or serverSelectionTimeoutMS in MongoClientOptions or per-operation options. For example: new MongoClient(uri, { socketTimeoutMS: -100 }) or collection.findOne({}, { timeoutMS: -5 }).
Common situations: Configuration loaded from environment variables parsed incorrectly (e.g. Number('-1')), arithmetic bugs that subtract too much from a timeout budget, or copy-paste errors in connection string options like ?socketTimeoutMS=-1.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- An operation cannot be given a timeoutMS setting when…
- Auth mechanism property ALLOWED_HOSTS must be an array of…
- Cannot parse namespace from
- Cannot use maxTimeMS with timeoutMS for explain commands.
- Currently only a ENVIRONMENT in
AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11).
Data as JSON: /api/errors/d083d37a9d7e3eff.
Report an issue: GitHub.
Appendix: 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 dce7939f86)