{"id":"66d5d9b5449f035e","repo":"mongodb/node-mongodb-native","slug":"operation-must-be-an-object-with-an-operation-key","errorCode":null,"errorMessage":"Operation must be an object with an operation key","messagePattern":"Operation must be an object with an operation key","errorType":"validation","errorClass":"MongoInvalidArgumentError","httpStatus":null,"severity":"error","filePath":"src/bulk/common.ts","lineNumber":1071,"sourceCode":"   * ```\n   */\n  find(selector: Document): FindOperators {\n    if (!selector) {\n      throw new MongoInvalidArgumentError('Bulk find operation must specify a selector');\n    }\n\n    // Save a current selector\n    this.s.currentOp = {\n      selector: selector\n    };\n\n    return new FindOperators(this);\n  }\n\n  /** Specifies a raw operation to perform in the bulk write. */\n  raw(op: AnyBulkWriteOperation): this {\n    if (op == null || typeof op !== 'object') {\n      throw new MongoInvalidArgumentError('Operation must be an object with an operation key');\n    }\n    if ('insertOne' in op) {\n      const forceServerObjectId = this.shouldForceServerObjectId();\n      const document =\n        op.insertOne && op.insertOne.document == null\n          ? // TODO(NODE-6003): remove support for omitting the `documents` subdocument in bulk inserts\n            (op.insertOne as Document)\n          : op.insertOne.document;\n\n      maybeAddIdToDocuments(this.collection, document, { forceServerObjectId });\n\n      return this.addToOperationsList(BatchType.INSERT, document);\n    }\n\n    if ('replaceOne' in op || 'updateOne' in op || 'updateMany' in op) {\n      if ('replaceOne' in op) {\n        if ('q' in op.replaceOne) {\n          throw new MongoInvalidArgumentError('Raw operations are not allowed');","sourceCodeStart":1053,"sourceCodeEnd":1089,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/3366c21a6311e02f1be91da982f9b93d3cce99a0/src/bulk/common.ts#L1053-L1089","documentation":"Thrown by BulkOperationBase.raw(op) when op is null/undefined or not a plain object. The raw() entry point expects a single bulk operation descriptor shaped like { insertOne: {...} } or { updateOne: {...} } and keys off the operation type. Anything that is not an object cannot be inspected for an operation key.","triggerScenarios":"Calling bulk.raw(null), bulk.raw(undefined), bulk.raw('string'), or bulk.raw(42). Pushing a primitive into an operations array that is then iterated and passed to raw().","commonSituations":"Parsing operations from JSON where a malformed entry yields a non-object; deserialization that produces nulls; spreading a list that contains holes.","solutions":["Ensure each op passed to raw() is a plain object with exactly one of the recognized operation keys.","Filter out nullish/non-object entries before calling raw(): ops.filter(o => o && typeof o === 'object').","Validate the operation shape with a schema check before enqueueing."],"exampleFix":"// before\nfor (const op of parsed) { bulk.raw(op); } // parsed contains null entries\n\n// after\nfor (const op of parsed) {\n  if (op == null || typeof op !== 'object') continue;\n  bulk.raw(op);\n}","handlingStrategy":"type-guard","validationCode":"function assertRawOp(op) {\n  if (op == null || typeof op !== 'object') {\n    throw new TypeError('bulk raw op must be a plain object with an operation key');\n  }\n}","typeGuard":"function isRawBulkOp(op) {\n  const keys = ['insertOne','updateOne','updateMany','replaceOne','deleteOne','deleteMany'];\n  return op != null && typeof op === 'object' && keys.some(k => k in op);\n}","tryCatchPattern":"try {\n  bulk.raw(op);\n} catch (e) {\n  if (e instanceof MongoInvalidArgumentError && /object with an operation key/.test(e.message)) {\n    // skip / log / sanitize the entry\n  }\n}","preventionTips":["Filter operation lists with ops.filter(o => o && typeof o === 'object') before iterating.","Validate parsed JSON against the bulk op schema before enqueueing."],"tags":["bulk-write","raw","validation","argument-error"],"analyzedSha":"3366c21a6311e02f1be91da982f9b93d3cce99a0","analyzedAt":"2026-08-04T13:40:15.335Z","schemaVersion":2}