mongodb/node-mongodb-native · error · MongoInvalidArgumentError

Cannot set timeoutMode without setting timeoutMS

Error message

Cannot set timeoutMode without setting timeoutMS

What it means

Thrown as a MongoInvalidArgumentError in the AbstractCursor constructor when timeoutMode is supplied but timeoutMS is not. timeoutMode only describes how an existing timeoutMS deadline is applied (per-iteration vs whole-cursor), so it is meaningless without a deadline. The constructor explicitly checks `options.timeoutMode != null` only in the `else` branch where `timeoutMS` is absent, and rejects the pairing to prevent silent no-op configuration.

Solutions

  1. Always set timeoutMS whenever you set timeoutMode.
  2. If you do not want a timeout, remove both timeoutMS and timeoutMode.
  3. Centralize timeout config so timeoutMode is only assigned together with a finite timeoutMS.

Example fix

// before: timeoutMode with no deadline
const cursor = collection.find(filter, { timeoutMode: 'iteration' });

// after: provide the deadline the mode applies to
const cursor = collection.find(filter, { timeoutMS: 1000, timeoutMode: 'iteration' });
Defensive patterns

Strategy: validation

Validate before calling

if (opts.timeoutMode != null && opts.timeoutMS == null) {
  throw new RangeError('timeoutMode requires timeoutMS to be set as well.');
}

Prevention

When it happens

Trigger: collection.find(filter, { timeoutMode: 'iteration' }) with no timeoutMS; passing a shared options object that sets timeoutMode but whose timeoutMS was conditionally deleted/undefined.

Common situations: Refactoring timeout code and dropping the timeoutMS line while leaving timeoutMode; spreading a base options object that always includes timeoutMode but only sometimes includes timeoutMS.

Understand the failure class

Related errors


AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11). Data as JSON: /api/errors/bed84e3365b5b59c. Report an issue: GitHub.

Appendix: source

Thrown at src/cursor/abstract_cursor.ts:310

                'Cannot specify maxAwaitTimeMS >= timeoutMS for a tailable awaitData cursor'
              );
          }

          this.cursorOptions.timeoutMode = CursorTimeoutMode.ITERATION;
        } else {
          this.cursorOptions.timeoutMode = CursorTimeoutMode.LIFETIME;
        }
      } else {
        if (options.tailable && options.timeoutMode === CursorTimeoutMode.LIFETIME) {
          throw new MongoInvalidArgumentError(
            "Cannot set tailable cursor's timeoutMode to LIFETIME"
          );
        }
        this.cursorOptions.timeoutMode = options.timeoutMode;
      }
    } else {
      if (options.timeoutMode != null)
        throw new MongoInvalidArgumentError('Cannot set timeoutMode without setting timeoutMS');
    }

    // Set for initial command
    this.cursorOptions.omitMaxTimeMS =
      this.cursorOptions.timeoutMS != null &&
      ((this.cursorOptions.timeoutMode === CursorTimeoutMode.ITERATION &&
        !this.cursorOptions.tailable) ||
        (this.cursorOptions.tailable && !this.cursorOptions.awaitData));

    const readConcern = ReadConcern.fromOptions(options);
    if (readConcern) {
      this.cursorOptions.readConcern = readConcern;
    }

    if (typeof options.batchSize === 'number') {
      this.cursorOptions.batchSize = options.batchSize;
    }

View on GitHub (pinned to dce7939f86)