mongodb/node-mongodb-native · error · MongoInvalidArgumentError
Argument "replacement" must be an object
Error message
Argument "replacement" must be an object
What it means
FindOneAndReplaceOperation's constructor (src/operations/find_and_modify.ts:236) requires the `replacement` argument to be a non-null object. The replacement is a full document that substitutes the matched document, so it must be a plain document without update operators. Passing null/undefined/primitive throws a MongoInvalidArgumentError.
Source
Thrown at src/operations/find_and_modify.ts:236
return document;
}
}
/** @internal */
export class FindOneAndReplaceOperation extends FindAndModifyOperation {
private replacement: Document;
constructor(
collection: Collection,
filter: Document,
replacement: Document,
options: FindOneAndReplaceOptions
) {
if (filter == null || typeof filter !== 'object') {
throw new MongoInvalidArgumentError('Argument "filter" must be an object');
}
if (replacement == null || typeof replacement !== 'object') {
throw new MongoInvalidArgumentError('Argument "replacement" must be an object');
}
if (hasAtomicOperators(replacement)) {
throw new MongoInvalidArgumentError('Replacement document must not contain atomic operators');
}
super(collection, filter, options);
this.replacement = replacement;
}
override buildCommandDocument(
connection: Connection,
session?: ClientSession
): Document & FindAndModifyCmdBase {
const document = super.buildCommandDocument(connection, session);
document.update = this.replacement;
configureFindAndModifyCmdBaseUpdateOpts(document, this.options);
return document;View on GitHub (pinned to 3366c21a63)
Solutions
- Pass a full replacement document: collection.findOneAndReplace(filter, { name: 'new', qty: 5 }).
- If you need atomic operators like $set, use findOneAndUpdate instead of findOneAndReplace.
- Ensure the replacement variable is a defined object before the call.
Example fix
// before
await collection.findOneAndReplace({ _id }, { $set: { name: 'x' } }); // wrong API
// after
// for a full replacement:
await collection.findOneAndReplace({ _id }, { name: 'x', qty: 0 });
// or use findOneAndUpdate for atomic operators:
await collection.findOneAndUpdate({ _id }, { $set: { name: 'x' } }); Defensive patterns
Strategy: validation
Validate before calling
function assertReplacement(doc: unknown): asserts doc is Record<string, unknown> {
if (doc == null || typeof doc !== 'object' || Array.isArray(doc)) {
throw new TypeError('findOneAndReplace: replacement must be a plain object');
}
} Type guard
const isValidReplacement = (d: unknown): d is Record<string, unknown> => d != null && typeof d === 'object' && !Array.isArray(d);
Prevention
- Pass a full replacement document, not an update with operators.
- Use findOneAndUpdate if you need $set/$inc/etc.
- Validate that the replacement variable is defined before calling.
When it happens
Trigger: Calling collection.findOneAndReplace(filter, null), collection.findOneAndReplace(filter, undefined), or passing a non-object as replacement.
Common situations: Omitting the replacement argument, passing a partial update with $set operators (which belongs in findOneAndUpdate), or a variable that resolved to undefined.
Related errors
- Argument "filter" must be an object
- Replacement document must not contain atomic operators
- Argument "update" must be an object
- Query filter must be a plain object or ObjectId
- ClientSession must be from the same MongoClient
AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04).
Data as JSON: /data/errors/29e259707377c2ff.json.
Report an issue: GitHub.