{"record":{"id":"8ea69d14e72e7000","repo":"mongodb/node-mongodb-native","slug":"option-readpreference-must-be-a-readpreference-i","errorCode":null,"errorMessage":"Option \"readPreference\" must be a ReadPreference instance","messagePattern":"Option \"readPreference\" must be a ReadPreference instance","errorType":"exception","errorClass":"MongoInvalidArgumentError","httpStatus":null,"severity":"error","filePath":"src/cmap/wire_protocol/shared.ts","lineNumber":23,"sourceCode":"import type { ServerDescription } from '../../sdam/server_description';\nimport type { Topology } from '../../sdam/topology';\nimport { TopologyDescription } from '../../sdam/topology_description';\nimport type { Connection } from '../connection';\n\nexport interface ReadPreferenceOption {\n  readPreference?: ReadPreferenceLike;\n}\n\nexport function getReadPreference(options?: ReadPreferenceOption): ReadPreference {\n  // Default to command version of the readPreference.\n  let readPreference = options?.readPreference ?? ReadPreference.primary;\n\n  if (typeof readPreference === 'string') {\n    readPreference = ReadPreference.fromString(readPreference);\n  }\n\n  if (!(readPreference instanceof ReadPreference)) {\n    throw new MongoInvalidArgumentError(\n      'Option \"readPreference\" must be a ReadPreference instance'\n    );\n  }\n\n  return readPreference;\n}\n\nexport function isSharded(topologyOrServer?: Topology | Server | Connection): boolean {\n  if (topologyOrServer == null) {\n    return false;\n  }\n\n  if (topologyOrServer.description && topologyOrServer.description.type === ServerType.Mongos) {\n    return true;\n  }\n\n  // NOTE: This is incredibly inefficient, and should be removed once command construction\n  // happens based on `Server` not `Topology`.","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/dce7939f86fb283e167ad709955abedb7bf23124/src/cmap/wire_protocol/shared.ts#L5-L41","documentation":"Thrown by getReadPreference when the readPreference option is neither a string nor an instance of ReadPreference. After attempting string->instance conversion, the function asserts instanceof ReadPreference and raises a MongoInvalidArgumentError if it fails. This is a client-side argument validation error, fully under the caller's control.","triggerScenarios":"Fires at src/cmap/wire_protocol/shared.ts:23 when options.readPreference is a non-string, non-ReadPreference value (e.g. a plain object like {mode:'secondary'} or a number). Triggered on any read operation (find, aggregate, count, listDatabases) or when setting collection/db-level read preferences.","commonSituations":"Passing {mode: 'secondary'} instead of 'secondary' or new ReadPreference('secondary'); passing a string the driver cannot parse (e.g. 'SECONDARY' works but typos do not); migrating code that built read preference objects manually; spreading untyped config from env/JSON without coercion.","solutions":["Pass a valid string mode: 'primary' | 'primaryPreferred' | 'secondary' | 'secondaryPreferred' | 'nearest'.","Or construct a ReadPreference instance: new ReadPreference('secondary').","If loading config from JSON, coerce to string before passing.","Check for typos and stray wrapping objects in the option."],"exampleFix":"// before\ncollection.find({}, { readPreference: { mode: 'secondary' } });\n\n// after\ncollection.find({}, { readPreference: 'secondary' });","handlingStrategy":"type-guard","validationCode":"const RP_MODES = ['primary','primaryPreferred','secondary','secondaryPreferred','nearest'] as const;\nfunction asReadPreference(v: unknown) {\n  if (typeof v === 'string' && (RP_MODES as readonly string[]).includes(v)) return v;\n  if (v instanceof ReadPreference) return v;\n  throw new TypeError(`Invalid readPreference: ${String(v)}`);\n}","typeGuard":"import { ReadPreference } from 'mongodb';\nfunction isValidReadPreference(v: unknown): v is string | ReadPreference {\n  if (v instanceof ReadPreference) return true;\n  if (typeof v === 'string') {\n    return ['primary','primaryPreferred','secondary','secondaryPreferred','nearest'].includes(v);\n  }\n  return false;\n}","tryCatchPattern":null,"preventionTips":["Pass readPreference as a string mode or a ReadPreference instance only.","Coerce config loaded from JSON/env to a string before passing.","Type the option field so TypeScript rejects plain objects."],"tags":["read-preference","validation","configuration","typescript"],"backgroundTag":null,"analyzedSha":"dce7939f86fb283e167ad709955abedb7bf23124","analyzedAt":"2026-08-11T04:54:53.215Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}