mongodb/node-mongodb-native · error · MongoInvalidArgumentError

Invalid read preference: ${r}

Error message

Invalid read preference: ${r}

What it means

Thrown by `ReadPreference.translate` when `options.readPreference` is present but is neither a string, a ReadPreference instance, nor a plain object carrying a string `mode`/`preference` field. The translate helper is used to normalize read preference options before command execution (read_preference.ts:191). Whatever value was passed does not match any accepted shape.

Source

Thrown at src/read_preference.ts:191

  /**
   * Replaces options.readPreference with a ReadPreference instance
   */
  static translate(options: ReadPreferenceLikeOptions): ReadPreferenceLikeOptions {
    if (options.readPreference == null) return options;
    const r = options.readPreference;

    if (typeof r === 'string') {
      options.readPreference = new ReadPreference(r);
    } else if (r && !(r instanceof ReadPreference) && typeof r === 'object') {
      const mode = r.mode || r.preference;
      if (mode && typeof mode === 'string') {
        options.readPreference = new ReadPreference(mode, r.tags, {
          maxStalenessSeconds: r.maxStalenessSeconds
        });
      }
    } else if (!(r instanceof ReadPreference)) {
      throw new MongoInvalidArgumentError(`Invalid read preference: ${r}`);
    }

    return options;
  }

  /**
   * Validate if a mode is legal
   *
   * @param mode - The string representing the read preference mode.
   */
  static isValid(mode: string): boolean {
    const VALID_MODES = new Set([
      ReadPreference.PRIMARY,
      ReadPreference.PRIMARY_PREFERRED,
      ReadPreference.SECONDARY,
      ReadPreference.SECONDARY_PREFERRED,
      ReadPreference.NEAREST,
      null

View on GitHub (pinned to 3366c21a63)

Solutions

  1. Provide a valid mode string ('primary' | 'primaryPreferred' | 'secondary' | 'secondaryPreferred' | 'nearest').
  2. Pass a `ReadPreference` instance built via `new ReadPreference(mode)` or `ReadPreference.fromString(mode)`.
  3. If using an object form, ensure it has a string `mode` (or `preference`) property.

Example fix

// before
find({}, { readPreference: { tags: [{ region: 'eu' }] } });
// after
find({}, { readPreference: { mode: 'nearest', tags: [{ region: 'eu' }] } });
Defensive patterns

Strategy: validation

Validate before calling

function normalizeReadPref(rp) {
  if (typeof rp === 'string' || rp instanceof ReadPreference) return rp;
  if (rp && typeof rp === 'object' && typeof (rp.mode ?? rp.preference) === 'string') return rp;
  throw new TypeError('readPreference must be a string, ReadPreference, or { mode: string }');
}

Type guard

function isValidReadPrefInput(rp) {
  if (rp == null) return true;
  if (typeof rp === 'string') return true;
  if (rp instanceof ReadPreference) return true;
  return typeof rp === 'object' && typeof (rp.mode ?? rp.preference) === 'string';
}

Prevention

When it happens

Trigger: Setting `readPreference` to a number, boolean, array, or an object that lacks a `mode` (e.g. `{ tags: [...] }` with no mode); passing a BSON document or class instance where a read preference is expected.

Common situations: Typo in the option name so an unrelated value lands in `readPreference`; constructing options dynamically and forgetting the mode field; deserializing a read preference from JSON that omits `mode`.

Related errors


AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04). Data as JSON: /data/errors/8d9e28e6992453d4.json. Report an issue: GitHub.