mongodb/node-mongodb-native · error · MongoInvalidArgumentError
Update document requires atomic operators
Error message
Update document requires atomic operators
What it means
Thrown by UpdateOneOperation's constructor when the update argument to collection.updateOne() has no atomic operators. Identical guard and rationale as findOneAndUpdate (error 300): updateOne must mutate via $set/$inc/etc. or an aggregation pipeline; a plain document is rejected client-side. MongoInvalidArgumentError.
Source
Thrown at src/operations/update.ts:146
command.comment = options.comment;
}
return command;
}
}
/** @internal */
export class UpdateOneOperation extends UpdateOperation {
constructor(
ns: MongoDBCollectionNamespace,
filter: Document,
update: Document,
options: UpdateOptions
) {
super(ns, [makeUpdateStatement(filter, update, { ...options, multi: false })], options);
if (!hasAtomicOperators(update, options)) {
throw new MongoInvalidArgumentError('Update document requires atomic operators');
}
}
override handleOk(
response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>
): UpdateResult {
const res = super.handleOk(response);
// @ts-expect-error Explain typing is broken
if (this.explain != null) return res;
if (res.code) throw new MongoServerError(res);
if (res.writeErrors) throw new MongoServerError(res.writeErrors[0]);
return {
acknowledged: this.writeConcern?.w !== 0,
modifiedCount: res.nModified ?? res.n,
upsertedId:View on GitHub (pinned to 3366c21a63)
Solutions
- Wrap changes in $set / $inc / $push etc.: { $set: { field: value } }.
- If you meant whole-document replacement, use collection.replaceOne(filter, replacement).
- For conditional/expressive updates pass an aggregation pipeline array.
- Verify the call signature: updateOne(filter, update, options).
Example fix
// before
await collection.updateOne({ _id: 1 }, { status: 'active' });
// after
await collection.updateOne({ _id: 1 }, { $set: { status: 'active' } }); Defensive patterns
Strategy: validation
Validate before calling
function isValidUpdate(doc) {
return Array.isArray(doc) || (doc != null && typeof doc === 'object' &&
Object.keys(doc).some(k => k.startsWith('$')));
}
if (!isValidUpdate(update)) throw new Error('updateOne needs $ operators or a pipeline');
await collection.updateOne(filter, update); Type guard
function isAtomicUpdate(doc): doc is Record<string, unknown> {
return Array.isArray(doc) || (doc != null && typeof doc === 'object' &&
Object.keys(doc).some(k => k.startsWith('$')));
} Prevention
- Use updateOne only with operator/pipeline updates; use replaceOne for full docs.
- Centralize update construction in helpers that always wrap fields in $set.
- Add tests covering empty/dynamic update paths.
When it happens
Trigger: collection.updateOne(filter, { field: value }) with no $-operator keys; passing a replacement-style document where an update document is required; argument-order mistakes placing a non-operator object in the update slot.
Common situations: Confusing updateOne with replaceOne; dynamic update builders yielding a bare object on some code path; migrating field assignment code into MongoDB without wrapping in $set.
Related errors
- Update document requires atomic operators
- Update document requires atomic operators
- Replacement document must not contain atomic operators
- Selector must be a valid JavaScript object
- Document must be a valid JavaScript object
AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04).
Data as JSON: /data/errors/3f49ebc88ecb27b8.json.
Report an issue: GitHub.