{"record":{"id":"70d6fb31c2b63700","repo":"mongodb/node-mongodb-native","slug":"client-bulk-write-replace-models-must-not-contain","errorCode":null,"errorMessage":"Client bulk write replace models must not contain atomic modifiers (start with $) and must not be empty.","messagePattern":"Client bulk write replace models must not contain atomic modifiers \\(start with \\$\\) and must not be empty\\.","errorType":"exception","errorClass":"MongoAPIError","httpStatus":null,"severity":"error","filePath":"src/operations/client_bulk_write/command_builder.ts","lineNumber":440,"sourceCode":"  updateMods: WithoutId<Document>;\n  hint?: Hint;\n  upsert?: boolean;\n  collation?: CollationOptions;\n  sort?: SortForCmd;\n}\n\n/**\n * Build the replace one operation.\n * @param model - The replace one model.\n * @param index - The namespace index.\n * @returns the operation.\n */\nexport const buildReplaceOneOperation = (\n  model: ClientReplaceOneModel<Document>,\n  index: number\n): ClientReplaceOneOperation => {\n  if (hasAtomicOperators(model.replacement)) {\n    throw new MongoAPIError(\n      'Client bulk write replace models must not contain atomic modifiers (start with $) and must not be empty.'\n    );\n  }\n\n  const document: ClientReplaceOneOperation = {\n    update: index,\n    multi: false,\n    filter: model.filter,\n    updateMods: model.replacement\n  };\n  if (model.hint) {\n    document.hint = model.hint;\n  }\n  if (model.upsert) {\n    document.upsert = model.upsert;\n  }\n  if (model.collation) {\n    document.collation = model.collation;","sourceCodeStart":422,"sourceCodeEnd":458,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/dce7939f86fb283e167ad709955abedb7bf23124/src/operations/client_bulk_write/command_builder.ts#L422-L458","documentation":"Thrown when a ReplaceOne client bulk write model's replacement document is empty or contains keys that start with '$'. Per the bulk write spec, replaceOne must take a full replacement document (no atomic operators); if you need $ operators, use updateOne or updateMany instead.","triggerScenarios":"Passing replaceOne: { namespace, filter, replacement: { $set: {...} } } or replacement: {} to client.bulkWrite. Also triggered by accidentally putting $set/$inc inside the replacement field.","commonSituations":"Copy-pasting an update document into a replaceOne model; refactoring between update and replace paths without adjusting the document shape; building replacement dynamically and ending up empty.","solutions":["Move $ operators into an updateOne or updateMany model instead of replaceOne.","Ensure the replacement field is a non-empty plain document with no $-prefixed keys.","Add a pre-flight type guard that rejects replacement documents whose first key starts with '$'."],"exampleFix":"// before\nawait client.bulkWrite([{\n  replaceOne: { namespace: 'db.coll', filter: { _id }, replacement: { $set: { a: 1 } } }\n}]);\n\n// after (use updateOne for $ operators)\nawait client.bulkWrite([{\n  updateOne: { namespace: 'db.coll', filter: { _id }, update: { $set: { a: 1 } } }\n}]);\n// or a true replacement\nawait client.bulkWrite([{\n  replaceOne: { namespace: 'db.coll', filter: { _id }, replacement: { a: 1, b: 2 } }\n}]);","handlingStrategy":"type-guard","validationCode":"function isValidReplacement(doc) {\n  if (!doc || typeof doc !== 'object' || Object.keys(doc).length === 0) return false;\n  return Object.keys(doc).every(k => !k.startsWith('$'));\n}","typeGuard":"const isReplacementDoc = (v: unknown): v is Record<string, unknown> =>\n  v != null && typeof v === 'object' && Object.keys(v as object).length > 0 &&\n  Object.keys(v as object).every(k => !k.startsWith('$'));","tryCatchPattern":null,"preventionTips":["Reserve replaceOne for full-document overwrites with no $ operators.","Switch to updateOne if you find $set creeping into the replacement."],"tags":["bulk-write","replace","api-misuse"],"backgroundTag":null,"analyzedSha":"dce7939f86fb283e167ad709955abedb7bf23124","analyzedAt":"2026-08-11T04:54:53.215Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}