mongodb/node-mongodb-native · error · MongoInvalidArgumentError

Could not serialize operation to BSON

Error message

Could not serialize operation to BSON

What it means

Thrown while building a client bulk write command when BSON.serialize() fails on a per-model operation document. The underlying serialization error is attached as `cause`. Typical causes are values BSON cannot encode: undefined nested values (depending on ignoreUndefined), circular references, custom class instances, symbols, BigInt beyond int64, or functions.

Source

Thrown at src/operations/client_bulk_write/command_builder.ts:136

    while (this.currentModelIndex < this.models.length) {
      const model = this.models[this.currentModelIndex];
      const ns = model.namespace;
      const nsIndex = namespaces.get(ns);

      // Multi updates are not retryable.
      if (model.name === 'deleteMany' || model.name === 'updateMany') {
        this.isBatchRetryable = false;
      }

      if (nsIndex != null) {
        // Build the operation and serialize it to get the bytes buffer.
        const operation = buildOperation(model, nsIndex, this.pkFactory, this.options);
        let operationBuffer;
        try {
          operationBuffer = BSON.serialize(operation);
        } catch (cause) {
          throw new MongoInvalidArgumentError(`Could not serialize operation to BSON`, { cause });
        }

        validateBufferSize('ops', operationBuffer, maxBsonObjectSize);

        // Check if the operation buffer can fit in the command. If it can,
        // then add the operation to the document sequence and increment the
        // current length as long as the ops don't exceed the maxWriteBatchSize.
        if (
          commandLength + operationBuffer.length < maxMessageSizeBytes &&
          command.ops.documents.length < maxWriteBatchSize
        ) {
          // Pushing to the ops document sequence returns the total byte length of the document sequence.
          commandLength = MESSAGE_OVERHEAD_BYTES + command.ops.push(operation, operationBuffer);
          // Increment the builder's current model index.
          this.currentModelIndex++;
        } else {
          // The operation cannot fit in the current command and will need to
          // go in the next batch. Exit the loop.

View on GitHub (pinned to 3366c21a63)

Solutions

  1. Inspect err.cause for the exact field and BSON type error, then sanitize that value.
  2. Strip non-serializable keys (functions, symbols, undefined) before building the model, or convert class instances to plain objects.
  3. Break circular references or use a custom serializer; consider ignoreUndefined if undefined handling is the issue.

Example fix

// before
await client.bulkWrite([{
  namespace: 'db.coll',
  name: 'insertOne',
  document: someMongooseDoc // class instance, fails BSON
}]);

// after
await client.bulkWrite([{
  namespace: 'db.coll',
  name: 'insertOne',
  document: someMongooseDoc.toObject()
}]);
Defensive patterns

Strategy: validation

Validate before calling

function toPlain(v) {
  return v == null || typeof v !== 'object' ? v
    : Array.isArray(v) ? v.map(toPlain)
    : Object.fromEntries(Object.entries(v).filter(([,x]) => x !== undefined && typeof x !== 'function').map(([k,x]) => [k, toPlain(x)]));
}

Type guard

function isPlainSerializable(v): boolean {
  if (v === undefined || typeof v === 'function' || typeof v === 'symbol') return false;
  if (typeof v !== 'object') return true;
  try { JSON.stringify(v); return true; } catch { return false; }
}

Try / catch

try { await client.bulkWrite(models); } catch (e) {
  if (e instanceof MongoInvalidArgumentError && /serialize operation/.test(e.message)) {
    console.error('Serialization failed:', e.cause);
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing client.bulkWrite() a model whose filter/update/document contains a non-serializable value: circular object, class instance, Map/Set, symbol keys, undefined where not allowed, or a value exceeding BSON type limits.

Common situations: Inserting ORM/Mongoose documents directly; objects with circular refs after JSON.parse of revivers; accidentally including function properties; using Decimal128/BSON types incorrectly.

Related errors


AI-assisted analysis of mongodb/node-mongodb-native@3366c21a63 (2026-08-04). Data as JSON: /data/errors/d86a8998dd381917.json. Report an issue: GitHub.