mongodb/node-mongodb-native · error · MongoInvalidArgumentError

bulkWrite only supports insertOne, updateOne, updateMany…

Error message

bulkWrite only supports insertOne, updateOne, updateMany, deleteOne, deleteMany

What it means

Thrown as MongoInvalidArgumentError at the end of BulkOperationBase.raw() (src/bulk/common.ts:1152) when the operation object does not match any recognized bulk write operation shape. raw() dispatches on the presence of insertOne/replaceOne/updateOne/updateMany/deleteOne/deleteMany keys; if none is present, it falls through to this catch-all error.

Solutions

  1. Verify each op has exactly one of: insertOne, updateOne, updateMany, replaceOne, deleteOne, deleteMany.
  2. Check for typos (insert vs insertOne, update vs updateOne) and remove extra wrapper layers.
  3. Log the offending op to see its actual keys before the call.

Example fix

// before
await coll.bulkWrite([
  { insert: { document: { a: 1 } } },
  { update: { filter: {}, set: { b: 2 } } }
]);

// after
await coll.bulkWrite([
  { insertOne: { document: { a: 1 } } },
  { updateOne: { filter: {}, update: { $set: { b: 2 } } } }
]);
Defensive patterns

Strategy: type-guard

Validate before calling

const SUPPORTED = new Set(['insertOne','updateOne','updateMany','replaceOne','deleteOne','deleteMany']);

function isSupportedBulkOp(op: unknown): op is Record<string, unknown> {
  if (op == null || typeof op !== 'object') return false;
  const keys = Object.keys(op);
  return keys.length === 1 && SUPPORTED.has(keys[0]);
}

const bad = ops.filter(o => !isSupportedBulkOp(o));
if (bad.length) {
  throw new Error('unsupported bulk op keys: ' + bad.map(o => Object.keys(o)[0]).join(', '));
}
await coll.bulkWrite(ops);

Type guard

type AnyBulkOp =
  | { insertOne: { document: Record<string, unknown> } }
  | { updateOne: { filter: Record<string, unknown>; update: Record<string, unknown> | Record<string, unknown>[] } }
  | { updateMany: { filter: Record<string, unknown>; update: Record<string, unknown> | Record<string, unknown>[] } }
  | { replaceOne: { filter: Record<string, unknown>; replacement: Record<string, unknown> } }
  | { deleteOne: { filter: Record<string, unknown> } }
  | { deleteMany: { filter: Record<string, unknown> } };

const SUPPORTED = new Set(['insertOne','updateOne','updateMany','replaceOne','deleteOne','deleteMany']);
function isAnyBulkOp(op: unknown): op is AnyBulkOp {
  if (op == null || typeof op !== 'object') return false;
  const keys = Object.keys(op);
  return keys.length === 1 && SUPPORTED.has(keys[0]);
}

Try / catch

try {
  await coll.bulkWrite(ops);
} catch (e) {
  if (e instanceof MongoInvalidArgumentError && /only supports/.test(e.message)) {
    // log each op's keys to find the typo / unknown shape, then fix and retry
    console.error(ops.map(o => Object.keys(o)));
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing an operation with a typo or unsupported key, e.g. { insert: {...} }, { update: {...} }, { remove: {...} }, or a completely unknown shape like { foo: 1 }. Also triggered by extra/wrapper layers such as { op: { insertOne: {...} } } where the inner shape is nested one level too deep.

Common situations: Typos in operation keys, version drift (using a key from an older/newer driver), wrapping ops in an extra object, or building ops from a schema that does not match the bulkWrite input contract.

Related errors


AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11). Data as JSON: /api/errors/5985a25b761fd284. Report an issue: GitHub.

Appendix: source

Thrown at src/bulk/common.ts:1152

      }
      return this.addToOperationsList(
        BatchType.DELETE,
        makeDeleteStatement(op.deleteOne.filter, { ...op.deleteOne, limit: 1 })
      );
    }

    if ('deleteMany' in op) {
      if ('q' in op.deleteMany) {
        throw new MongoInvalidArgumentError('Raw operations are not allowed');
      }
      return this.addToOperationsList(
        BatchType.DELETE,
        makeDeleteStatement(op.deleteMany.filter, { ...op.deleteMany, limit: 0 })
      );
    }

    // otherwise an unknown operation was provided
    throw new MongoInvalidArgumentError(
      'bulkWrite only supports insertOne, updateOne, updateMany, deleteOne, deleteMany'
    );
  }

  get length(): number {
    return this.s.currentIndex;
  }

  get bsonOptions(): BSONSerializeOptions {
    return this.s.bsonOptions;
  }

  get writeConcern(): WriteConcern | undefined {
    return this.s.writeConcern;
  }

  get batches(): Batch[] {
    const batches = [...this.s.batches];

View on GitHub (pinned to dce7939f86)