{"record":{"id":"449923bb9cf1f6f1","repo":"mongodb/node-mongodb-native","slug":"replacement-document-must-not-contain-atomic-opera-449923","errorCode":null,"errorMessage":"Replacement document must not contain atomic operators","messagePattern":"Replacement document must not contain atomic operators","errorType":"exception","errorClass":"MongoInvalidArgumentError","httpStatus":null,"severity":"error","filePath":"src/operations/update.ts","lineNumber":235,"sourceCode":"  upsert?: boolean;\n  /** Map of parameter names and values that can be accessed using $$var (requires MongoDB 5.0). */\n  let?: Document;\n  /** Specifies the sort order for the documents matched by the filter. */\n  sort?: Sort;\n}\n\n/** @internal */\nexport class ReplaceOneOperation extends UpdateOperation {\n  constructor(\n    ns: MongoDBCollectionNamespace,\n    filter: Document,\n    replacement: Document,\n    options: ReplaceOptions\n  ) {\n    super(ns, [makeUpdateStatement(filter, replacement, { ...options, multi: false })], options);\n\n    if (hasAtomicOperators(replacement)) {\n      throw new MongoInvalidArgumentError('Replacement document must not contain atomic operators');\n    }\n  }\n\n  override handleOk(\n    response: InstanceType<typeof this.SERVER_COMMAND_RESPONSE_TYPE>\n  ): UpdateResult {\n    const res = super.handleOk(response);\n\n    // @ts-expect-error Explain typing is broken\n    if (this.explain != null) return res;\n    if (res.code) throw new MongoServerError(res);\n    if (res.writeErrors) throw new MongoServerError(res.writeErrors[0]);\n\n    return {\n      acknowledged: this.writeConcern?.w !== 0,\n      modifiedCount: res.nModified ?? res.n,\n      upsertedId:\n        Array.isArray(res.upserted) && res.upserted.length > 0 ? res.upserted[0]._id : null,","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/dce7939f86fb283e167ad709955abedb7bf23124/src/operations/update.ts#L217-L253","documentation":"Thrown as a MongoInvalidArgumentError by the ReplaceOneOperation constructor when the replacement document contains atomic operators (keys beginning with '$'). replaceOne substitutes the entire matched document with the supplied replacement, so field-update operators like $set are illegal; those belong to updateOne/updateMany. The check uses hasAtomicOperators() at update.ts:234.","triggerScenarios":"Calling collection.replaceOne(filter, { $set: { a: 1 } }) instead of collection.updateOne. Any replacement whose first key starts with '$' triggers this.","commonSituations":"Copy-pasting an update document into a replaceOne call; confusion between replaceOne (full document) and updateOne (operators); refactoring and forgetting to switch APIs.","solutions":["If you meant partial updates with operators, use collection.updateOne(filter, { $set: { a: 1 } }).","If you meant a full replacement, remove all '$'-prefixed keys and supply the complete document.","Add a preflight check that no replacement key starts with '$' before calling replaceOne."],"exampleFix":"// before\nawait collection.replaceOne({ _id: id }, { $set: { status: 'on' } });\n\n// after\nawait collection.updateOne({ _id: id }, { $set: { status: 'on' } });","handlingStrategy":"validation","validationCode":"function isPlainReplacement(v: unknown) {\n  return typeof v === 'object' && v !== null && !Array.isArray(v)\n    && !Object.keys(v).some(k => k.startsWith('$'));\n}\nif (!isPlainReplacement(replacement)) {\n  throw new TypeError('replacement must not contain atomic operators; use updateOne for $ ops');\n}\nawait collection.replaceOne(filter, replacement);","typeGuard":"function isReplacementDoc(v: unknown): v is Record<string, unknown> {\n  return typeof v === 'object' && v !== null && !Array.isArray(v)\n    && Object.keys(v).every(k => !k.startsWith('$'));\n}","tryCatchPattern":null,"preventionTips":["Remember: replaceOne = full document, updateOne = $ operators.","Run a key-prefix check on dynamic replacements before calling replaceOne.","When refactoring between update and replace, switch the API and the document shape together."],"tags":["validation","replace-one","atomic-operators","replacement","argument"],"backgroundTag":null,"analyzedSha":"dce7939f86fb283e167ad709955abedb7bf23124","analyzedAt":"2026-08-11T04:54:53.215Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}