mongodb/node-mongodb-native · error · MongoInvalidArgumentError

Operation must be an object with an operation key

Error message

Operation must be an object with an operation key

What it means

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.

Source

Thrown at src/bulk/common.ts:1071

   * ```
   */
  find(selector: Document): FindOperators {
    if (!selector) {
      throw new MongoInvalidArgumentError('Bulk find operation must specify a selector');
    }

    // Save a current selector
    this.s.currentOp = {
      selector: selector
    };

    return new FindOperators(this);
  }

  /** Specifies a raw operation to perform in the bulk write. */
  raw(op: AnyBulkWriteOperation): this {
    if (op == null || typeof op !== 'object') {
      throw new MongoInvalidArgumentError('Operation must be an object with an operation key');
    }
    if ('insertOne' in op) {
      const forceServerObjectId = this.shouldForceServerObjectId();
      const document =
        op.insertOne && op.insertOne.document == null
          ? // TODO(NODE-6003): remove support for omitting the `documents` subdocument in bulk inserts
            (op.insertOne as Document)
          : op.insertOne.document;

      maybeAddIdToDocuments(this.collection, document, { forceServerObjectId });

      return this.addToOperationsList(BatchType.INSERT, document);
    }

    if ('replaceOne' in op || 'updateOne' in op || 'updateMany' in op) {
      if ('replaceOne' in op) {
        if ('q' in op.replaceOne) {
          throw new MongoInvalidArgumentError('Raw operations are not allowed');

View on GitHub (pinned to 3366c21a63)

Solutions

  1. Ensure each op passed to raw() is a plain object with exactly one of the recognized operation keys.
  2. Filter out nullish/non-object entries before calling raw(): ops.filter(o => o && typeof o === 'object').
  3. Validate the operation shape with a schema check before enqueueing.

Example fix

// before
for (const op of parsed) { bulk.raw(op); } // parsed contains null entries

// after
for (const op of parsed) {
  if (op == null || typeof op !== 'object') continue;
  bulk.raw(op);
}
Defensive patterns

Strategy: type-guard

Validate before calling

function assertRawOp(op) {
  if (op == null || typeof op !== 'object') {
    throw new TypeError('bulk raw op must be a plain object with an operation key');
  }
}

Type guard

function isRawBulkOp(op) {
  const keys = ['insertOne','updateOne','updateMany','replaceOne','deleteOne','deleteMany'];
  return op != null && typeof op === 'object' && keys.some(k => k in op);
}

Try / catch

try {
  bulk.raw(op);
} catch (e) {
  if (e instanceof MongoInvalidArgumentError && /object with an operation key/.test(e.message)) {
    // skip / log / sanitize the entry
  }
}

Prevention

When it happens

Trigger: 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().

Common situations: Parsing operations from JSON where a malformed entry yields a non-object; deserialization that produces nulls; spreading a list that contains holes.

Related errors


AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04). Data as JSON: /data/errors/66d5d9b5449f035e.json. Report an issue: GitHub.