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,
nullView on GitHub (pinned to 3366c21a63)
Solutions
- Provide a valid mode string ('primary' | 'primaryPreferred' | 'secondary' | 'secondaryPreferred' | 'nearest').
- Pass a `ReadPreference` instance built via `new ReadPreference(mode)` or `ReadPreference.fromString(mode)`.
- 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
- Validate dynamic read preferences against the known mode set before use.
- Prefer ReadPreference instances over ad-hoc objects.
- Add a runtime assert in config-loading code.
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
- Option "readPreference" must be a ReadPreference instance
- Primary read preference cannot be combined with hedge
- Missing required option `keyVaultNamespace`
- Invalid CANONICALIZE_HOST_NAME value: ${canonicalization}
- TOKEN_RESOURCE must be set in the auth mechanism properties
AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04).
Data as JSON: /data/errors/8d9e28e6992453d4.json.
Report an issue: GitHub.