mongodb/node-mongodb-native · error · MongoInvalidArgumentError

Document is larger than the maximum size

Error message

Document is larger than the maximum size ${this.s.maxBsonObjectSize}

What it means

Thrown as MongoInvalidArgumentError by OrderedBulkOperation.addToOperationsList() (src/bulk/ordered.ts:46) when a single operation document serializes to a BSON size greater than or equal to maxBsonObjectSize (16 MiB by default, returned by the server in the hello/handshake). The driver serializes the document up front to compute its size and rejects oversized ops before sending them, so the server never sees them.

Solutions

  1. Move large binary payloads to GridFS (bucket.uploadFromStream) or an object store and keep only a reference in the document.
  2. Trim or normalize embedded arrays and nested subdocuments that bloated the document.
  3. Confirm the server's actual limit (db.hello().maxBsonObjectSize) — it is normally 16777216; if a custom server reports less, size accordingly.
  4. Split a single huge update into per-field updates or stage the data in a side collection.

Example fix

// before: inline blob blows past 16 MiB
bulk.insert({ _id: 1, data: hugeBuffer });
await bulk.execute();

// after: store blob via GridFS, keep only metadata
const bucket = new MongoClient(uri).db().bucket();
const streamId = await new Promise((resolve, reject) => {
  const up = bucket.openUploadStream();
  up.end(hugeBuffer, () => resolve(up.id));
  up.on('error', reject);
});
bulk.insert({ _id: 1, fileId: streamId });
await bulk.execute();
Defensive patterns

Strategy: validation

Validate before calling

import { serialize } from 'bson';

const MAX_BSON = 16 * 1024 * 1024; // 16 MiB default; confirm with db.hello().maxBsonObjectSize

function isWithinBsonLimit(doc: unknown): boolean {
  try {
    return serialize(doc as Record<string, unknown>).length < MAX_BSON;
  } catch {
    return false;
  }
}

for (const op of ops) {
  const doc = 'insertOne' in op ? op.insertOne.document : undefined;
  if (doc && !isWithinBsonLimit(doc)) {
    throw new Error('document exceeds 16 MiB BSON limit; move large payloads to GridFS');
  }
}

Type guard

function isReasonablySmallDoc(doc: unknown, max = 16 * 1024 * 1024): boolean {
  try {
    return serialize(doc as Record<string, unknown>).length < max;
  } catch {
    return false;
  }
}

Try / catch

try {
  await bulk.execute();
} catch (e) {
  if (e instanceof MongoInvalidArgumentError && /larger than the maximum size/.test(e.message)) {
    // offload large binary fields to GridFS, then rebuild and re-execute
  } else throw e;
}

Prevention

When it happens

Trigger: Adding an insert/update/replacement document whose serialized size is >= maxBsonObjectSize (e.g. embedding a large binary/blob inline). Guarded by `if (bsonSize >= this.s.maxBsonObjectSize)` at src/bulk/ordered.ts:44.

Common situations: Storing large files/images inline instead of via GridFS, deeply nested structures, large arrays of embedded subdocuments, or a server whose maxBsonObjectSize was lowered. Also seen when a document grew organically past 16 MiB.

Related errors


AI-assisted analysis of mongodb/node-mongodb-native@dce7939f86 (2026-08-11). Data as JSON: /api/errors/4ea40c398bec961a. Report an issue: GitHub.

Appendix: source

Thrown at src/bulk/ordered.ts:46

    if (this.s.usingAutoEncryption) {
      bsonSize = BSON.calculateObjectSize(document, {
        checkKeys: false,
        ignoreUndefined: false
      } as any);
    } else {
      const bson = this.s.bsonOptions;
      buffer = BSON.serialize(document, {
        checkKeys: this.s.checkKeys,
        ignoreUndefined: bson.ignoreUndefined,
        serializeFunctions: bson.serializeFunctions
      });
      bsonSize = buffer.length;
    }

    // Throw error if the doc is bigger than the max BSON size
    if (bsonSize >= this.s.maxBsonObjectSize)
      // TODO(NODE-3483): Change this to MongoBSONError
      throw new MongoInvalidArgumentError(
        `Document is larger than the maximum size ${this.s.maxBsonObjectSize}`
      );

    // Create a new batch object if we don't have a current one
    if (this.s.currentBatch == null) {
      this.s.currentBatch = new Batch(batchType, this.s.currentIndex);
    }

    const maxKeySize = this.s.maxKeySize;

    // Check if we need to create a new batch
    if (
      // New batch if we exceed the max batch op size
      this.s.currentBatchSize + 1 >= this.s.maxWriteBatchSize ||
      // New batch if we exceed the maxBatchSizeBytes. Only matters if batch already has a doc,
      // since we can't sent an empty batch
      (this.s.currentBatchSize > 0 &&
        this.s.currentBatchSizeBytes + maxKeySize + bsonSize >= this.s.maxBatchSizeBytes) ||

View on GitHub (pinned to dce7939f86)