{"record":{"id":"991e591036f57ad4","repo":"mongodb/node-mongodb-native","slug":"replacement-document-must-not-contain-atomic-opera","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/find_and_modify.ts","lineNumber":240,"sourceCode":"/** @internal */\nexport class FindOneAndReplaceOperation extends FindAndModifyOperation {\n  private replacement: Document;\n  constructor(\n    collection: Collection,\n    filter: Document,\n    replacement: Document,\n    options: FindOneAndReplaceOptions\n  ) {\n    if (filter == null || typeof filter !== 'object') {\n      throw new MongoInvalidArgumentError('Argument \"filter\" must be an object');\n    }\n\n    if (replacement == null || typeof replacement !== 'object') {\n      throw new MongoInvalidArgumentError('Argument \"replacement\" must be an object');\n    }\n\n    if (hasAtomicOperators(replacement)) {\n      throw new MongoInvalidArgumentError('Replacement document must not contain atomic operators');\n    }\n\n    super(collection, filter, options);\n    this.replacement = replacement;\n  }\n\n  override buildCommandDocument(\n    connection: Connection,\n    session?: ClientSession\n  ): Document & FindAndModifyCmdBase {\n    const document = super.buildCommandDocument(connection, session);\n    document.update = this.replacement;\n    configureFindAndModifyCmdBaseUpdateOpts(document, this.options);\n    return document;\n  }\n}\n\n/** @internal */","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/dce7939f86fb283e167ad709955abedb7bf23124/src/operations/find_and_modify.ts#L222-L258","documentation":"Thrown as a MongoInvalidArgumentError by the FindOneAndReplaceOperation constructor when the replacement document contains keys beginning with '$' (atomic operators like $set, $inc). A replace operation substitutes the entire document, so field-update operators are illegal in the replacement; those belong to findOneAndUpdate. The check uses hasAtomicOperators() at find_and_modify.ts:239.","triggerScenarios":"Calling collection.findOneAndReplace(filter, { $set: { a: 1 } }) instead of collection.findOneAndUpdate. Any replacement whose first key starts with '$' triggers this.","commonSituations":"Copy-pasting an update document into a replace call; confusion between replaceOne/findOneAndReplace (full document) and updateOne/findOneAndUpdate (operators); refactoring code and forgetting to switch APIs.","solutions":["If you meant partial updates with operators, use collection.findOneAndUpdate(filter, { $set: { a: 1 } }) instead.","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 findOneAndReplace."],"exampleFix":"// before\nawait collection.findOneAndReplace({ _id: id }, { $set: { status: 'on' } });\n\n// after\nawait collection.findOneAndUpdate({ _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 findOneAndUpdate for $ ops');\n}\nawait collection.findOneAndReplace(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: replace = full document, update = $ operators.","Run a key-prefix check on dynamic replacements before calling findOneAndReplace."],"tags":["validation","find-one-and-replace","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"}