{"record":{"id":"d86a8998dd381917","repo":"mongodb/node-mongodb-native","slug":"could-not-serialize-operation-to-bson","errorCode":null,"errorMessage":"Could not serialize operation to BSON","messagePattern":"Could not serialize operation to BSON","errorType":"exception","errorClass":"MongoInvalidArgumentError","httpStatus":null,"severity":"error","filePath":"src/operations/client_bulk_write/command_builder.ts","lineNumber":136,"sourceCode":"\n    while (this.currentModelIndex < this.models.length) {\n      const model = this.models[this.currentModelIndex];\n      const ns = model.namespace;\n      const nsIndex = namespaces.get(ns);\n\n      // Multi updates are not retryable.\n      if (model.name === 'deleteMany' || model.name === 'updateMany') {\n        this.isBatchRetryable = false;\n      }\n\n      if (nsIndex != null) {\n        // Build the operation and serialize it to get the bytes buffer.\n        const operation = buildOperation(model, nsIndex, this.pkFactory, this.options);\n        let operationBuffer;\n        try {\n          operationBuffer = BSON.serialize(operation);\n        } catch (cause) {\n          throw new MongoInvalidArgumentError(`Could not serialize operation to BSON`, { cause });\n        }\n\n        validateBufferSize('ops', operationBuffer, maxBsonObjectSize);\n\n        // Check if the operation buffer can fit in the command. If it can,\n        // then add the operation to the document sequence and increment the\n        // current length as long as the ops don't exceed the maxWriteBatchSize.\n        if (\n          commandLength + operationBuffer.length < maxMessageSizeBytes &&\n          command.ops.documents.length < maxWriteBatchSize\n        ) {\n          // Pushing to the ops document sequence returns the total byte length of the document sequence.\n          commandLength = MESSAGE_OVERHEAD_BYTES + command.ops.push(operation, operationBuffer);\n          // Increment the builder's current model index.\n          this.currentModelIndex++;\n        } else {\n          // The operation cannot fit in the current command and will need to\n          // go in the next batch. Exit the loop.","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/mongodb/node-mongodb-native/blob/dce7939f86fb283e167ad709955abedb7bf23124/src/operations/client_bulk_write/command_builder.ts#L118-L154","documentation":"Thrown when BSON.serialize fails on a single client-side bulk write operation. The driver wraps the underlying BSON error (cause) so you can see exactly why serialization aborted. Common BSON-serialization failures include values that BSON cannot represent: undefined nested in documents (with the driver's checkKeys behavior), functions, Symbols, circular references, or oversized keys.","triggerScenarios":"Passing a model whose filter/update/document contains a function, Symbol, circular reference, or a key containing '.' or starting with '$' where disallowed. Also a 32-bit-int overflow or a BigInt outside the supported range.","commonSituations":"Storing class instances with method references; serializing request objects from HTTP libraries that contain circular refs; accidentally including a Mongoose document with non-plain-object internals; passing Decimal128/Long constructed incorrectly.","solutions":["Inspect error.cause — it carries the exact BSON error message and path.","Strip non-serializable fields (functions, symbols, undefined) before building the model; convert class instances to plain objects.","If circular references are involved, serialize with a replacer or use EJSON for the problematic values.","For BigInt values, wrap with bson.Long or bson.Int32 as appropriate."],"exampleFix":"// before\nawait client.bulkWrite([{\n  insertOne: { namespace: 'db.coll', document: { req, handler } } // req is a circular http request object\n}]);\n\n// after\nawait client.bulkWrite([{\n  insertOne: { namespace: 'db.coll', document: { id: req.id, url: req.url } }\n}]);","handlingStrategy":"try-catch","validationCode":"// Pre-validate with the same BSON the driver uses\nimport { serialize } from 'bson';\ntry {\n  serialize(opDocument, { checkKeys: false });\n} catch (e) {\n  throw new Error(`Document will not serialize: ${e.message}`);\n}","typeGuard":"const isPlainSerializable = (v: unknown): boolean => {\n  if (v == null || typeof v !== 'object') return typeof v !== 'function' && typeof v !== 'symbol';\n  return Object.values(v).every(isPlainSerializable);\n};","tryCatchPattern":"try {\n  await client.bulkWrite(models);\n} catch (e) {\n  if (/Could not serialize operation to BSON/.test(e.message)) {\n    // inspect e.cause for the exact field, fix, and retry that batch\n  }\n}","preventionTips":["Convert class instances to plain objects before inserting.","Avoid putting request/response objects with circular refs into documents."],"tags":["bulk-write","bson","serialization"],"backgroundTag":null,"analyzedSha":"dce7939f86fb283e167ad709955abedb7bf23124","analyzedAt":"2026-08-11T04:54:53.215Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}