Saltar al contenido principal
MongoDB

MongoDB: E11000 duplicate key error collection

Solución al error E11000 duplicate key en MongoDB. Cómo manejar índices únicos y evitar conflictos de duplicados en tus colecciones.

Error: MongoServerError: E11000 duplicate key error collection

¿Por qué ocurre?

MongoDB lanza E11000 cuando intentas insertar o actualizar un documento que viola un índice único (unique index). Las causas más comunes son: - El campo `email` u otro campo único ya existe en la colección - Un índice único compuesto se viola (combinación de campos ya existe) - Datos de prueba duplicados al sembrar (seeding) la base de datos - Race condition: dos requests simultáneos intentan crear el mismo recurso

Solución paso a paso

1. Capturar el error correctamente (Mongoose)

const mongoose = require('mongoose');

try { await User.create({ email: 'test@example.com' }); } catch (error) { if (error.code === 11000) { // Extraer el campo duplicado const field = Object.keys(error.keyValue)[0]; const value = error.keyValue[field]; throw new Error(El ${field} '${value}' ya está registrado); } throw error; }

2. Usar findOneAndUpdate con upsert (upsert seguro)

// En lugar de create(), usar upsert para manejar duplicados
const user = await User.findOneAndUpdate(
  { email: 'test@example.com' },      // filtro
  { $setOnInsert: { name: 'Fran' } }, // solo si es nuevo
  { upsert: true, new: true }
);

3. Verificar antes de insertar

const existing = await User.findOne({ email });
if (existing) {
  return res.status(409).json({ error: 'Email ya registrado' });
}
await User.create({ email, name });

4. Ver índices de una colección

// Mongoose
const indexes = await User.collection.getIndexes();
console.log(indexes);

// MongoDB Shell db.users.getIndexes()

5. Eliminar un índice problemático (con cuidado)

// Solo si realmente no necesitas unicidad
await User.collection.dropIndex('email_1');

// En el schema, eliminar unique: true email: { type: String, required: true } // sin unique

6. Middleware Mongoose para manejo global

userSchema.post('save', function(error, doc, next) {
  if (error.name === 'MongoServerError' && error.code === 11000) {
    next(new Error('Email duplicado'));
  } else {
    next(error);
  }
});

Cómo evitarlo en el futuro

- Siempre captura el código de error `11000` específicamente en operaciones de escritura - Usa `findOneAndUpdate` con `upsert` para operaciones idempotentes - En APIs REST, devuelve HTTP 409 (Conflict) cuando hay duplicados - Usa transacciones MongoDB para operaciones que necesiten consistencia bajo concurrencia - Documenta qué campos tienen índice único en el schema de Mongoose

MongoDBMongooseíndice únicoduplicate keybase de datos

¿Quieres que una IA te ayude? Genera el prompt perfecto para tu error:

Generador de Prompts

¿Necesitas desarrollo a medida?

Apps web, IA, módulos ERP — cuéntame tu proyecto.