mongodb/node-mongodb-native · error · MongoParseError
ReadConcern must be an object, got
Error message
ReadConcern must be an object, got ${JSON.stringify(value)} What it means
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.
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.
Example fix
// before
new MongoClient(uri, { readConcern: 'majority' });
// after
new MongoClient(uri, { readConcernLevel: 'majority' }); Defensive patterns
Strategy: type-guard
Validate before calling
import { ReadConcern } from 'mongodb';
function isReadConcernLike(v: unknown): boolean {
return v instanceof ReadConcern || (!!v && typeof v === 'object' && 'level' in v);
}
if (opts.readConcern != null && !isReadConcernLike(opts.readConcern)) {
throw new Error('readConcern must be { level } or a ReadConcern instance');
} Type guard
function isReadConcernLike(v: unknown): v is { level: string } { return !!v && typeof v === 'object' && 'level' in v; } Try / catch
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; } Prevention
- Use `readConcernLevel` for bare string levels.
- Type readConcern as `{ level: ReadConcernLevel }` in your config schema.
- Do not conflate readConcern (consistency) with readPreference (routing).
When it happens
Trigger: Passing `readConcern: 'majority'` (string), `readConcern: 1`, `readConcern: ['local']`, or `readConcern: { consistency: 'majority' }` (wrong key).
Common situations: 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.
Related errors
- compressors must be an array or a comma-delimited list of…
- Invalid WriteConcern cannot parse
- Option 'mongodbLogComponentSeverities' must be a non-null…
- Option 'mongodbLogPath' must be of type 'stderr' | 'stdout'…
- Option pkFactory must be an object with a createPk…
AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11).
Data as JSON: /api/errors/30e9801cb0750d03.
Report an issue: GitHub.
Appendix: source
Thrown at src/connection_string.ts:996
proxyPassword: {
type: 'string'
},
proxyPort: {
type: 'uint'
},
proxyUsername: {
type: 'string'
},
raw: {
default: false,
type: 'boolean'
},
readConcern: {
transform({ values: [value], options }) {
if (value instanceof ReadConcern || isRecord(value, ['level'] as const)) {
return ReadConcern.fromOptions({ ...options.readConcern, ...value });
}
throw new MongoParseError(`ReadConcern must be an object, got ${JSON.stringify(value)}`);
}
},
readConcernLevel: {
target: 'readConcern',
transform({ values: [level], options }) {
return ReadConcern.fromOptions({
...options.readConcern,
level: level as ReadConcernLevel
});
}
},
readPreference: {
default: ReadPreference.primary,
transform({ values: [value], options }) {
if (value instanceof ReadPreference) {
return ReadPreference.fromOptions({
readPreference: { ...options.readPreference, ...value },
...valueView on GitHub (pinned to dce7939f86)