{"record":{"id":"30e9801cb0750d03","repo":"mongodb/node-mongodb-native","slug":"readconcern-must-be-an-object-got-json-stringif","errorCode":null,"errorMessage":"ReadConcern must be an object, got ${JSON.stringify(value)}","messagePattern":"ReadConcern must be an object, got (.+?)","errorType":"exception","errorClass":"MongoParseError","httpStatus":null,"severity":"error","filePath":"src/connection_string.ts","lineNumber":996,"sourceCode":"  proxyPassword: {\n    type: 'string'\n  },\n  proxyPort: {\n    type: 'uint'\n  },\n  proxyUsername: {\n    type: 'string'\n  },\n  raw: {\n    default: false,\n    type: 'boolean'\n  },\n  readConcern: {\n    transform({ values: [value], options }) {\n      if (value instanceof ReadConcern || isRecord(value, ['level'] as const)) {\n        return ReadConcern.fromOptions({ ...options.readConcern, ...value });\n      }\n      throw new MongoParseError(`ReadConcern must be an object, got ${JSON.stringify(value)}`);\n    }\n  },\n  readConcernLevel: {\n    target: 'readConcern',\n    transform({ values: [level], options }) {\n      return ReadConcern.fromOptions({\n        ...options.readConcern,\n        level: level as ReadConcernLevel\n      });\n    }\n  },\n  readPreference: {\n    default: ReadPreference.primary,\n    transform({ values: [value], options }) {\n      if (value instanceof ReadPreference) {\n        return ReadPreference.fromOptions({\n          readPreference: { ...options.readPreference, ...value },\n          ...value","sourceCodeStart":978,"sourceCodeEnd":1014,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/dce7939f86fb283e167ad709955abedb7bf23124/src/connection_string.ts#L978-L1014","documentation":"The `readConcern` option must be either a ReadConcern instance or a record containing a `level` field; the transform at src/connection_string.ts:992 checks `value instanceof ReadConcern || isRecord(value, ['level'])`. Anything else — a string, number, array — throws MongoParseError at src/connection_string.ts:996. Use the separate `readConcernLevel` option to pass a bare level string.","triggerScenarios":"Passing `readConcern: 'majority'` (string), `readConcern: 1`, `readConcern: ['local']`, or `readConcern: { consistency: 'majority' }` (wrong key).","commonSituations":"Treating readConcern like readPreference (which does accept a string); copying the level string into the wrong option; ODM wrappers that pass through user strings unchanged.","solutions":["Use `readConcernLevel: 'majority'` for a bare string level.","Or pass an object: `readConcern: { level: 'majority' }`.","Or construct `new ReadConcern('majority')` and pass that instance."],"exampleFix":"// before\nnew MongoClient(uri, { readConcern: 'majority' });\n\n// after\nnew MongoClient(uri, { readConcernLevel: 'majority' });","handlingStrategy":"type-guard","validationCode":"import { ReadConcern } from 'mongodb';\nfunction isReadConcernLike(v: unknown): boolean {\n  return v instanceof ReadConcern || (!!v && typeof v === 'object' && 'level' in v);\n}\nif (opts.readConcern != null && !isReadConcernLike(opts.readConcern)) {\n  throw new Error('readConcern must be { level } or a ReadConcern instance');\n}","typeGuard":"function isReadConcernLike(v: unknown): v is { level: string } { return !!v && typeof v === 'object' && 'level' in v; }","tryCatchPattern":"try { client = new MongoClient(uri, opts); } catch (e) { if (e instanceof MongoParseError && /ReadConcern/.test(e.message)) { const lvl = (opts as any).readConcern; delete (opts as any).readConcern; opts.readConcernLevel = String(lvl); client = new MongoClient(uri, opts); } else throw e; }","preventionTips":["Use `readConcernLevel` for bare string levels.","Type readConcern as `{ level: ReadConcernLevel }` in your config schema.","Do not conflate readConcern (consistency) with readPreference (routing)."],"tags":["read-concern","configuration","type-error"],"backgroundTag":null,"analyzedSha":"dce7939f86fb283e167ad709955abedb7bf23124","analyzedAt":"2026-08-11T04:54:53.215Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}