mongodb/node-mongodb-native · error · MongoInvalidArgumentError
Raw operations are not allowed
Error message
Raw operations are not allowed
What it means
Thrown by BulkOperationBase.raw() when a replaceOne operation uses the raw wire-protocol field 'q' (e.g. { replaceOne: { q: {...}, u: {...} } }). The driver only accepts the user-facing shape { filter, replacement }; raw server-side statement shapes are rejected to prevent ambiguity and double-encoding.
Source
Thrown at src/bulk/common.ts:1089
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');
}
const updateStatement = makeUpdateStatement(
op.replaceOne.filter,
op.replaceOne.replacement,
{ ...op.replaceOne, multi: false }
);
if (hasAtomicOperators(updateStatement.u)) {
throw new MongoInvalidArgumentError('Replacement document must not use atomic operators');
}
return this.addToOperationsList(BatchType.UPDATE, updateStatement);
}
if ('updateOne' in op) {
if ('q' in op.updateOne) {
throw new MongoInvalidArgumentError('Raw operations are not allowed');
}
const updateStatement = makeUpdateStatement(op.updateOne.filter, op.updateOne.update, {
...op.updateOne,View on GitHub (pinned to 3366c21a63)
Solutions
- Rewrite the operation using the documented keys: { replaceOne: { filter: q, replacement: u } }.
- If you have raw statements, convert them with a mapper before passing to bulk.raw().
Example fix
// before
bulk.raw({ replaceOne: { q: { _id: 1 }, u: { name: 'a' } } });
// after
bulk.raw({ replaceOne: { filter: { _id: 1 }, replacement: { name: 'a' } } }); Defensive patterns
Strategy: validation
Validate before calling
function toUserReplaceOne(op) {
if ('q' in op.replaceOne || 'u' in op.replaceOne) {
return { replaceOne: { filter: op.replaceOne.q, replacement: op.replaceOne.u } };
}
return op;
} Type guard
function isUserFacingReplaceOne(op) {
return 'replaceOne' in op && !('q' in op.replaceOne);
} Try / catch
try {
bulk.raw(op);
} catch (e) {
if (/Raw operations are not allowed/.test(e.message)) {
op = normalizeOp(op); // map q/u -> filter/replacement
bulk.raw(op);
}
} Prevention
- Always build operations using the documented { filter, replacement } keys.
- Never paste operation shapes from profiler/oplog output directly into bulk.raw().
When it happens
Trigger: Passing { replaceOne: { q: filter, u: replacement } } to bulk.raw(). Constructing operations from serialized server statements or log dumps that use q/u field names.
Common situations: Copying operation shapes from MongoDB profiler output, oplog entries, or older driver internals that expose the q/u keys.
Related errors
- Replacement document must not use atomic operators
- Operation must be an object with an operation key
- bulkWrite only supports insertOne, updateOne, updateMany, de
- Update document requires atomic operators
- Bulk find operation must specify a selector
AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04).
Data as JSON: /data/errors/3a81aef9d1b278f1.json.
Report an issue: GitHub.