{"record":{"id":"c7b4d995bb4e67ea","repo":"mongodb/node-mongodb-native","slug":"client-bulk-write-update-models-must-only-contain","errorCode":null,"errorMessage":"Client bulk write update models must only contain atomic modifiers (start with $) and must not be empty.","messagePattern":"Client bulk write update models must only 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":373,"sourceCode":" * @param model - The update many model.\n * @param index - The namespace index.\n * @returns the operation.\n */\nexport const buildUpdateManyOperation = (\n  model: ClientUpdateManyModel<Document>,\n  index: number,\n  options: BSONSerializeOptions\n): ClientUpdateOperation => {\n  return createUpdateOperation(model, index, true, options);\n};\n\n/**\n * Validate the update document.\n * @param update - The update document.\n */\nfunction validateUpdate(update: Document, options: BSONSerializeOptions) {\n  if (!hasAtomicOperators(update, options)) {\n    throw new MongoAPIError(\n      'Client bulk write update models must only contain atomic modifiers (start with $) and must not be empty.'\n    );\n  }\n}\n\n/**\n * Creates a delete operation based on the parameters.\n */\nfunction createUpdateOperation(\n  model: ClientUpdateOneModel<Document> | ClientUpdateManyModel<Document>,\n  index: number,\n  multi: boolean,\n  options: BSONSerializeOptions\n): ClientUpdateOperation {\n  // Update documents provided in UpdateOne and UpdateMany write models are\n  // required only to contain atomic modifiers (i.e. keys that start with \"$\").\n  // Drivers MUST throw an error if an update document is empty or if the\n  // document's first key does not start with \"$\".","sourceCodeStart":355,"sourceCodeEnd":391,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/dce7939f86fb283e167ad709955abedb7bf23124/src/operations/client_bulk_write/command_builder.ts#L355-L391","documentation":"Thrown when an UpdateOne or UpdateMany client bulk write model has an update document that is empty or whose first key does not start with '$'. The driver enforces the cross-driver bulk write spec, which requires update models to use atomic operators only — replacement-style documents belong in ReplaceOne models.","triggerScenarios":"Passing updateOne: { namespace, filter, update: { field: value } } (no $set) or update: {} to client.bulkWrite. Also triggered by update documents whose first key is a non-$ field due to a typo like 'set' instead of '$set'.","commonSituations":"Migrating from collection.updateMany(filter, { field: value }) legacy code paths; copy-paste from replaceOne; building update documents dynamically and forgetting the operator wrapper.","solutions":["Wrap field changes in $set/$unset/$inc/etc.: { $set: { field: value } }.","If you genuinely want to replace the whole document, use a replaceOne model instead of updateOne/updateMany.","Validate the update document programmatically before sending — first key must start with '$' and the document must not be empty."],"exampleFix":"// before\nawait client.bulkWrite([{\n  updateOne: { namespace: 'db.coll', filter: { _id }, update: { status: 'done' } }\n}]);\n\n// after\nawait client.bulkWrite([{\n  updateOne: { namespace: 'db.coll', filter: { _id }, update: { $set: { status: 'done' } } }\n}]);","handlingStrategy":"type-guard","validationCode":"function isValidUpdate(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 isAtomicUpdate = (v: unknown): v is Record<string, object> =>\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":["Always wrap field changes in $set / $inc / $unset.","Use replaceOne when you want to overwrite the whole document."],"tags":["bulk-write","update","api-misuse"],"backgroundTag":null,"analyzedSha":"dce7939f86fb283e167ad709955abedb7bf23124","analyzedAt":"2026-08-11T04:54:53.215Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}