Skip to content

insertMany() clears pending document state after command errors with empty writeErrors #16648

Open

Description

@IbrahimHafez1

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to avoid duplication

Mongoose version

9.11.4; reproduced on master f59e13a

Node.js version

22.23.4

MongoDB server version

8.2.3

Description

When an insert command is rejected, the driver can throw a MongoBulkWriteError with writeErrors: [] and insertedCount: 0. insertMany() treats the empty array as evidence of per-operation results, includes all inputs in error.insertedDocs, and clears their isNew and modified state. No documents were inserted. A later save() attempts to update a nonexistent document and rejects with DocumentNotFoundError.

This occurs with both ordered and unordered inserts, including rawResult. Lean results also incorrectly claim that the documents were inserted.

Related #13579 handles a missing writeErrors property; this case has an empty array. #16607/#16608 concern preservation of individual WriteError instances. #16646/#16647 concern the separate bulkSave() path. I found no matching insertMany() fix in those changes.

Steps to Reproduce

Install mongoose@9.11.4 and mongodb-memory-server, then run this JavaScript script:

const mongoose = require('mongoose');
const { MongoMemoryServer } = require('mongodb-memory-server');

async function run() {
  const server = await MongoMemoryServer.create();
  try {
    await mongoose.connect(server.getUri());
    const Item = mongoose.model('Item', new mongoose.Schema({ name: String }));
    await Item.init();
    const doc = new Item({ name: 'pending' });
    const error = await Item.insertMany([doc], {
      ordered: false,
      writeConcern: { w: -1 }
    }).catch(error => error);
    console.log(error.name, error.code, error.writeErrors.length);
    // MongoBulkWriteError 9 0
    console.log(await Item.countDocuments(), error.insertedDocs.length);
    // 0 1
    console.log(doc.isNew, doc.isModified('name'));
    // false false
    await doc.save(); // DocumentNotFoundError: No document found for query ...
  } finally {
    await mongoose.disconnect();
    await server.stop();
  }
}
run().catch(console.error);

The invalid write concern deterministically produces a real server rejection before inserting any rows; the bug is how Mongoose classifies that rejection afterward.

Expected Behavior

Keep these documents pending and do not report them in insertedDocs. Preserve existing behavior when the driver explicitly confirms the entire valid batch was inserted, even if replication acknowledgement failed. An empty write-error array alone proves neither success nor failure of every operation.

I have a small fix and regression tests for ordered/unordered, raw/normal, lean, and confirmed inserts followed by a write-concern error. Unknown or partially confirmed outcomes still require application-level reconciliation; this is not a general safe-retry guarantee.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions