{"record":{"id":"3a81aef9d1b278f1","repo":"mongodb/node-mongodb-native","slug":"raw-operations-are-not-allowed","errorCode":null,"errorMessage":"Raw operations are not allowed","messagePattern":"Raw operations are not allowed","errorType":"exception","errorClass":"MongoInvalidArgumentError","httpStatus":null,"severity":"error","filePath":"src/bulk/common.ts","lineNumber":1089,"sourceCode":"      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');\n        }\n        const updateStatement = makeUpdateStatement(\n          op.replaceOne.filter,\n          op.replaceOne.replacement,\n          { ...op.replaceOne, multi: false }\n        );\n        if (hasAtomicOperators(updateStatement.u)) {\n          throw new MongoInvalidArgumentError('Replacement document must not use atomic operators');\n        }\n        return this.addToOperationsList(BatchType.UPDATE, updateStatement);\n      }\n\n      if ('updateOne' in op) {\n        if ('q' in op.updateOne) {\n          throw new MongoInvalidArgumentError('Raw operations are not allowed');\n        }\n        const updateStatement = makeUpdateStatement(op.updateOne.filter, op.updateOne.update, {\n          ...op.updateOne,","sourceCodeStart":1071,"sourceCodeEnd":1107,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/dce7939f86fb283e167ad709955abedb7bf23124/src/bulk/common.ts#L1071-L1107","documentation":"Thrown as MongoInvalidArgumentError inside BulkOperationBase.raw() (src/bulk/common.ts:1089) when a replaceOne operation object contains a 'q' key. The 'q' field is part of the server-side wire-protocol update statement shape (q/u), not the user-facing API shape (filter/replacement); the driver forbids passing already-encoded 'raw' operations through the public bulkWrite path to keep the API contract clean.","triggerScenarios":"Passing { replaceOne: { q: {...}, u: {...} } } to bulkOp.raw(...) (or collection.bulkWrite). The check is `if ('q' in op.replaceOne)` at src/bulk/common.ts:1088.","commonSituations":"Re-using wire-protocol payloads captured from a logger/proxy, building ops from generic { q, u } factories, or porting code that previously manipulated the low-level op format. Rarely accidental; usually a structural mismatch between captured and user-facing op shapes.","solutions":["Re-shape the operation to the user-facing form: { replaceOne: { filter: {...}, replacement: {...} } }.","If you have wire-protocol ops from a log, map q -> filter and u -> replacement (for replace) before passing them in.","Do not construct ops from generic { q, u } helpers; use the documented key names."],"exampleFix":"// before\nawait coll.bulkWrite([\n  { replaceOne: { q: { _id: 1 }, u: { name: 'Sam' } } }\n]);\n\n// after\nawait coll.bulkWrite([\n  { replaceOne: { filter: { _id: 1 }, replacement: { name: 'Sam' } } }\n]);","handlingStrategy":"validation","validationCode":"function isUserFacingReplaceOne(op: any): boolean {\n  return op && 'replaceOne' in op && !('q' in op.replaceOne) &&\n    'filter' in op.replaceOne && 'replacement' in op.replaceOne;\n}\n\nif (!isUserFacingReplaceOne(op)) {\n  throw new Error('replaceOne must use { filter, replacement }, not the wire { q, u } shape');\n}","typeGuard":"type UserReplaceOne = { replaceOne: { filter: Record<string, unknown>; replacement: Record<string, unknown> } };\n\nfunction isUserFacingReplaceOne(op: unknown): op is UserReplaceOne {\n  if (op == null || typeof op !== 'object') return false;\n  const r = (op as any).replaceOne;\n  return r != null && typeof r === 'object' &&\n    !('q' in r) && 'filter' in r && 'replacement' in r;\n}","tryCatchPattern":"try {\n  await coll.bulkWrite(ops);\n} catch (e) {\n  if (e instanceof MongoInvalidArgumentError && /Raw operations are not allowed/.test(e.message)) {\n    // map wire shape q/u -> filter/replacement, then retry\n  } else throw e;\n}","preventionTips":["Never pass wire-protocol { q, u } payloads to bulkWrite; always use { filter, replacement }.","When converting captured/logged ops, map q -> filter and u -> replacement.","Avoid generic { q, u } factories; use named keys matching the public API.","Add a lint/test that rejects ops containing a top-level 'q' key."],"tags":["bulk-write","raw","replace","wire-protocol","validation"],"backgroundTag":null,"analyzedSha":"dce7939f86fb283e167ad709955abedb7bf23124","analyzedAt":"2026-08-11T04:54:53.215Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}