{"record":{"id":"ec954d8c0576f227","repo":"Automattic/mongoose","slug":"operation-failed-with-validationerrors-length","errorCode":null,"errorMessage":"${operation} failed with ${validationErrors.length} Mongoose validation errors: ${preview} (operation is 'bulkWrite')","messagePattern":"(.+?) failed with (.+?) Mongoose validation errors: (.+?) \\(operation is 'bulkWrite'\\)","errorType":"exception","errorClass":"MongooseBulkWriteError","httpStatus":null,"severity":"error","filePath":"lib/model.js","lineNumber":3564,"sourceCode":"    if (error?.writeErrors) {\n      for (const writeError of error.writeErrors) {\n        writeErrorsByIndex[writeError.err.index] = writeError;\n      }\n    }\n    for (let i = 0; i < validOpIndexes.length; ++i) {\n      results[validOpIndexes[i]] = writeErrorsByIndex[i] ?? null;\n    }\n    if (error) {\n      if (validationErrors.length > 0) {\n        decorateBulkWriteResult(error, validationErrors, results);\n      }\n\n      await this.hooks.execPost('bulkWrite', this, [null], { error, filter: postFilter });\n    }\n\n    if (validationErrors.length > 0) {\n      if (options.throwOnValidationError) {\n        throw new MongooseBulkWriteError(\n          validationErrors,\n          results,\n          res,\n          'bulkWrite'\n        );\n      } else {\n        decorateBulkWriteResult(res, validationErrors, results);\n      }\n    }\n  }\n\n  await this.hooks.execPost('bulkWrite', this, [res], { filter: postFilter });\n\n  return res;\n}\n\n/**\n * Takes an array of documents, gets the changes and inserts/updates documents in the database","sourceCodeStart":3546,"sourceCodeEnd":3582,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/model.js#L3546-L3582","documentation":"After a bulkWrite whose ops partially failed schema casting, if validationErrors is non-empty and options.throwOnValidationError is true, Mongoose throws MongooseBulkWriteError with this message once the driver call finishes. Valid ops have already executed (any driver error is decorated and rethrown first), so this signals partial success: check .validationErrors for failed op indexes and the write result/res for what succeeded. Without the option, the result is returned decorated with mongoose.validationErrors.","triggerScenarios":"await Model.bulkWrite(mixedOps, { throwOnValidationError: true }) where at least one insertOne/replaceOne/updateOne op carries a document that fails validation (required, enum, custom validator).","commonSituations":"Batched sync jobs over third-party data where a subset of records fails new validation rules; partial schema tightening (new required field) leaving older producers non-compliant.","solutions":["Catch MongooseBulkWriteError, iterate err.validationErrors (op index + message), and re-enqueue/fix only the failed operations","Pre-validate each document with validateSync() before building ops so only valid ops are submitted","Fix the source records or adjust the schema (remove required, widen enum) for rules that reject legitimate data","Omit throwOnValidationError and read res.mongoose?.validationErrors from the returned result when partial completion is acceptable"],"exampleFix":"// before\nawait User.bulkWrite(ops, { throwOnValidationError: true });\n\n// after\ntry {\n  await User.bulkWrite(ops, { throwOnValidationError: true });\n} catch (err) {\n  if (err.name === 'MongooseBulkWriteError') {\n    const bad = err.validationErrors.map(v => v.index);\n    await retryQueue.push(...ops.filter((_, i) => bad.includes(i)));\n  } else throw err;\n}","handlingStrategy":"validation","validationCode":"const validated = ops.map(op => {\n  if (op.insertOne) {\n    const err = new Model(op.insertOne.document).validateSync();\n    return { op, err };\n  }\n  return { op, err: null };\n});\nconst good = validated.filter(x => !x.err).map(x => x.op);\nconst bad = validated.filter(x => x.err);\nif (bad.length) report(bad);\nawait Model.bulkWrite(good);","typeGuard":null,"tryCatchPattern":"try {\n  const res = await Model.bulkWrite(ops, { throwOnValidationError: true });\n} catch (err) {\n  if (err.name === 'MongooseBulkWriteError') {\n    const failedIndexes = err.validationErrors.map(v => v.index);\n    const failedOps = ops.filter((_, i) => failedIndexes.includes(i));\n    // valid ops already executed; requeue failedOps for repair\n  } else throw err;\n}","preventionTips":["Treat MongooseBulkWriteError from bulkWrite as partial success: reconcile via validationErrors indexes","Pre-validate insertOne/replaceOne documents with validateSync() before building ops","Log op indexes with source record ids at build time so failures map back to inputs"],"tags":["mongoose","bulkwrite","validation","partial-success","bulk"],"backgroundTag":"schema-validation-failed","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}