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
- Verify each op has exactly one of: insertOne, updateOne, updateMany, replaceOne, deleteOne, deleteMany.
- Check for typos (insert vs insertOne, update vs updateOne) and remove extra wrapper layers.
- 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
- Validate each op has exactly one supported key before calling bulkWrite.
- Type the ops array as AnyBulkWriteOperation[] to surface shape errors at compile time.
- Watch for typos (insert vs insertOne) and extra wrapper layers.
- Log op keys in tests so shape regressions show up early.
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
- Argument "operations" must be an array of documents
- Bulk find operation must specify a selector
- Document is larger than the maximum size
- Document is larger than the maximum size
- Invalid BulkOperation, Batch cannot be empty
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)