mongodb/node-mongodb-native · error · MongoParseError

ReadConcern must be an object, got ${JSON.stringify(value)}

Error message

ReadConcern must be an object, got ${JSON.stringify(value)}

What it means

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.

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 },
          ...value

View on GitHub (pinned to 3366c21a63)

Solutions

  1. Use `readConcern: { level: 'local' }` (valid levels: 'local','available','majority','linearizable','snapshot')
  2. Or use the `readConcernLevel: 'local'` option which takes the string directly
  3. Use `new ReadConcern('local')`

Example fix

// before
new MongoClient(uri, { readConcern: 'local' });
// after
new MongoClient(uri, { readConcernLevel: 'local' });
// or
new MongoClient(uri, { readConcern: { level: 'local' } });
Defensive patterns

Strategy: type-guard

Validate before calling

import { ReadConcern } from 'mongodb';
function isReadConcernLike(v) {
  return v instanceof ReadConcern || (v != null && typeof v === 'object' && 'level' in v);
}
if (options.readConcern && !isReadConcernLike(options.readConcern)) {
  throw new TypeError('readConcern must be { level } or a ReadConcern');
}

Type guard

import { ReadConcern } from 'mongodb';
function isReadConcernLike(v) {
  return v instanceof ReadConcern || (!!v && typeof v === 'object' && 'level' in v);
}

Prevention

When it happens

Trigger: `{ readConcern: 'local' }` (string — should be `{ level: 'local' }` or use `readConcernLevel`); `{ readConcern: 1 }`; `{ readConcern: ['local'] }`.

Common situations: Passing a level string directly instead of an object; confusing `readConcern` with the `readConcernLevel` shorthand; mixing up with read preference.

Related errors


AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04). Data as JSON: /data/errors/30e9801cb0750d03.json. Report an issue: GitHub.