Automattic/mongoose · error · MongooseBulkWriteError
bulkWrite failed with ${validationErrors.length} Mongoose va
Error message
bulkWrite failed with ${validationErrors.length} Mongoose validation errors: ${preview} What it means
Connection.prototype.bulkWrite() validates every op ({ model, name, document, ... }) against the model's schema before sending anything to MongoDB. With { ordered: false } it collects per-op failures (schema validation, unregistered model name, unrecognized op name) into validationErrors; normally invalid ops are skipped and reported on the result, but with options.throwOnValidationError: true Mongoose throws a MongooseBulkWriteError instead. This throw site (lib/connection.js:560) fires only when every op in the batch failed validation, so validOps is empty and nothing was sent to the server.
Source
Thrown at lib/connection.js:560
)
);
} else {
validOps.push({ ...op, namespace: Model.namespace() });
validOpIndexes.push(i);
}
}
if (asyncValidations.length > 0) {
await Promise.all(asyncValidations);
}
validationErrors = validationErrors.
sort((v1, v2) => v1.index - v2.index).
map(v => v.error);
if (validOps.length === 0) {
if (options.throwOnValidationError && validationErrors.length) {
throw new MongooseBulkWriteError(
validationErrors,
results,
res,
'bulkWrite'
);
}
const BulkWriteResult = this.base.driver.get().BulkWriteResult;
const res = new BulkWriteResult(getDefaultBulkwriteResult(), false);
return decorateBulkWriteResult(res, validationErrors, results);
}
let error;
[res, error] = await this.client.bulkWrite(validOps, options).
then(res => ([res, null])).
catch(err => ([null, err]));
for (let i = 0; i < validOpIndexes.length; ++i) {
results[validOpIndexes[i]] = null;View on GitHub (pinned to 49cdab0136)
Solutions
- Catch the error and inspect err.validationErrors and err.results to see exactly which ops failed and why, then fix those documents
- Pre-validate each document before batching: const vErr = new conn.model(op.model)(op.document).validateSync()
- Drop throwOnValidationError and handle partial success via res.mongoose.validationErrors
- Relax or correct the schema rules if the strictness is unintended
Example fix
// before
await conn.bulkWrite(ops, { ordered: false, throwOnValidationError: true }); // throws when ALL ops invalid
// after: pre-validate, split good/bad ops
const good = [], bad = [];
for (const op of ops) {
const Model = conn.model(op.model);
const vErr = new Model(op.document ?? {}).validateSync();
if (vErr) bad.push(op); else good.push(op);
}
if (good.length) await conn.bulkWrite(good, { ordered: false }); Defensive patterns
Strategy: try-catch
Validate before calling
for (const op of ops) {
const Model = conn.model(op.model);
const vErr = new Model(op.document ?? {}).validateSync();
if (vErr) throw new Error(`op ${op.name} invalid: ${vErr.message}`);
} Try / catch
try {
const res = await conn.bulkWrite(ops, { ordered: false, throwOnValidationError: true });
} catch (err) {
if (err?.name === 'MongooseBulkWriteError') {
// nothing was written (validOps was empty)
err.validationErrors.forEach(v => console.error(v.message));
return;
}
throw err;
} Prevention
- Pre-validate every op's document with validateSync() before batching
- Without throwOnValidationError, always inspect res.mongoose.validationErrors for skipped ops
- Keep bulk imports on the same schema definitions as the app so validators cannot drift
When it happens
Trigger: await conn.bulkWrite([{ model: 'Test', name: 'insertOne', document: { /* missing required field */ } }], { ordered: false, throwOnValidationError: true }) where all documents violate schema rules (required, enum, match, custom validators), or every op references an unregistered model name or unrecognized op name.
Common situations: Bulk import / ETL jobs feeding unvalidated data; a schema tightened (new required field or enum) without cleaning historical inputs; opting into all-or-nothing semantics with throwOnValidationError.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/758dbd172b071d97.
Report an issue: GitHub.