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

  1. Ensure all timeout options (timeoutMS, socketTimeoutMS, serverSelectionTimeoutMS, waitQueueTimeoutMS) are non-negative integers.
  2. If timeouts come from env vars or config, validate them with a parseUnsignedInteger-style guard before passing to the client.
  3. 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

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

Related errors


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)