{"id":"ddbec88a31d46538","repo":"mongodb/node-mongodb-native","slug":"update-operations-require-that-all-atomic-operator","errorCode":null,"errorMessage":"Update operations require that all atomic operators have defined values, but none were provided.","messagePattern":"Update operations require that all atomic operators have defined values, but none were provided\\.","errorType":"exception","errorClass":"MongoInvalidArgumentError","httpStatus":null,"severity":"error","filePath":"src/utils.ts","lineNumber":481,"sourceCode":"        return true;\n      }\n    }\n    return false;\n  }\n\n  const keys = Object.keys(doc);\n  // In this case we need to throw if all the atomic operators are undefined.\n  if (options?.ignoreUndefined) {\n    let allUndefined = true;\n    for (const key of keys) {\n      // eslint-disable-next-line no-restricted-syntax\n      if (doc[key] !== undefined) {\n        allUndefined = false;\n        break;\n      }\n    }\n    if (allUndefined) {\n      throw new MongoInvalidArgumentError(\n        'Update operations require that all atomic operators have defined values, but none were provided.'\n      );\n    }\n  }\n\n  return keys.length > 0 && keys[0][0] === '$';\n}\n\nexport function resolveTimeoutOptions<T extends Partial<TimeoutContextOptions>>(\n  client: MongoClient,\n  options: T\n): T &\n  Pick<\n    MongoClient['s']['options'],\n    'timeoutMS' | 'serverSelectionTimeoutMS' | 'waitQueueTimeoutMS' | 'socketTimeoutMS'\n  > {\n  const { socketTimeoutMS, serverSelectionTimeoutMS, waitQueueTimeoutMS, timeoutMS } =\n    client.s.options;","sourceCodeStart":463,"sourceCodeEnd":499,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/3366c21a6311e02f1be91da982f9b93d3cce99a0/src/utils.ts#L463-L499","documentation":"Thrown by hasAtomicOperators() when invoked with the ignoreUndefined option and every key of the update document has an undefined value. The driver uses this to reject updateOne/updateMany/bulk update statements where the operator payloads ($set, $inc, ...) collapse entirely to undefined, which would otherwise send a no-op or malformed command. It surfaces as a MongoInvalidArgumentError and protects against silently writing nothing. Call sites include update.ts, find_and_modify.ts, bulk/common.ts, and client_bulk_write/command_builder.ts.","triggerScenarios":"Calling `coll.updateOne({ _id }, { $set: { field: someValue } })` where someValue is undefined; building an update from optional TS object fields whose values are all undefined; spreading a possibly-empty partial into $set.","commonSituations":"TypeScript optional fields hydrated to undefined; dynamic update builders that conditionally assign keys but the condition is never true; payload deserialization dropping values; refactors that leave $set:{a:undefined}.","solutions":["Strip undefined values from the update payload before sending: filter the object so $set only contains defined values.","If the update is genuinely empty, skip the updateOne call entirely rather than sending it.","Default optional fields to concrete values or guard each field with a truthy check before adding it to $set."],"exampleFix":"// before\nawait coll.updateOne({ _id }, { $set: { name: user.name, age: user.age } });\n// user.name and user.age both undefined => MongoInvalidArgumentError\n\n// after\nconst setFields = Object.fromEntries(\n  Object.entries({ name: user.name, age: user.age }).filter(([, v]) => v !== undefined)\n);\nif (Object.keys(setFields).length === 0) return; // nothing to update\nawait coll.updateOne({ _id }, { $set: setFields });","handlingStrategy":"validation","validationCode":"function cleanUpdate(update: Record<string, any>): Record<string, any> | null {\n  const out: Record<string, any> = {};\n  for (const [op, fields] of Object.entries(update)) {\n    const defined = Object.fromEntries(Object.entries(fields).filter(([, v]) => v !== undefined));\n    if (Object.keys(defined).length > 0) out[op] = defined;\n  }\n  return Object.keys(out).length > 0 ? out : null;\n}\n\nconst clean = cleanUpdate({ $set: { name: user.name, age: user.age } });\nif (clean) await coll.updateOne({ _id }, clean);","typeGuard":"function hasDefinedAtomicValues(doc: Record<string, any>): boolean {\n  return Object.values(doc).some(v => v !== undefined);\n}","tryCatchPattern":null,"preventionTips":["Build $set/$inc objects from filtered entries that drop undefined values.","Skip the write entirely when the cleaned update is empty.","Avoid spreading partial optionals directly into atomic operators."],"tags":["crud","update","typescript","validation"],"analyzedSha":"3366c21a6311e02f1be91da982f9b93d3cce99a0","analyzedAt":"2026-08-04T13:40:15.335Z","schemaVersion":2}