{"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/3366c21a6311e02f1be91da982f9b93d3cce99a0/src/connection_string.ts#L978-L1014","documentation":"The `readConcern` option must be a `ReadConcern` instance or a plain object containing a `level` key. The transform (src/connection_string.ts:991-997) checks `value instanceof ReadConcern || isRecord(value, ['level'])`; any other shape throws.","triggerScenarios":"`{ readConcern: 'local' }` (string — should be `{ level: 'local' }` or use `readConcernLevel`); `{ readConcern: 1 }`; `{ readConcern: ['local'] }`.","commonSituations":"Passing a level string directly instead of an object; confusing `readConcern` with the `readConcernLevel` shorthand; mixing up with read preference.","solutions":["Use `readConcern: { level: 'local' }` (valid levels: 'local','available','majority','linearizable','snapshot')","Or use the `readConcernLevel: 'local'` option which takes the string directly","Use `new ReadConcern('local')`"],"exampleFix":"// before\nnew MongoClient(uri, { readConcern: 'local' });\n// after\nnew MongoClient(uri, { readConcernLevel: 'local' });\n// or\nnew MongoClient(uri, { readConcern: { level: 'local' } });","handlingStrategy":"type-guard","validationCode":"import { ReadConcern } from 'mongodb';\nfunction isReadConcernLike(v) {\n  return v instanceof ReadConcern || (v != null && typeof v === 'object' && 'level' in v);\n}\nif (options.readConcern && !isReadConcernLike(options.readConcern)) {\n  throw new TypeError('readConcern must be { level } or a ReadConcern');\n}","typeGuard":"import { ReadConcern } from 'mongodb';\nfunction isReadConcernLike(v) {\n  return v instanceof ReadConcern || (!!v && typeof v === 'object' && 'level' in v);\n}","tryCatchPattern":null,"preventionTips":["Use { level: '...' } or the readConcernLevel shorthand","Do not pass a bare level string to readConcern","Distinguish readConcern (durability/consistency) from readPreference (routing)"],"tags":["read-concern","configuration","options"],"analyzedSha":"3366c21a6311e02f1be91da982f9b93d3cce99a0","analyzedAt":"2026-08-04T13:40:15.335Z","schemaVersion":2}