¿Qué es el error Mongoose Cast para ObjectId falló para el valor XXX en la ruta “_id”?

Al enviar una solicitud a /customers/41224d776a326fb40f000001 y no existe un documento con _id 41224d776a326fb40f000001 , doc es null y estoy devolviendo un 404 :

  Controller.prototype.show = function(id, res) { this.model.findById(id, function(err, doc) { if (err) { throw err; } if (!doc) { res.send(404); } return res.send(doc); }); }; 

Sin embargo, cuando _id no coincide con lo que Mongoose espera como “formato” (supongo), por ejemplo, con GET /customers/foo se devuelve un error extraño:

CastError: Cast to ObjectId falló para el valor “foo” en la ruta “_id”.

Entonces, ¿qué es este error?

El método findById de findById arroja el parámetro id al tipo del campo _id del modelo para que pueda consultar adecuadamente el documento correspondiente. Este es un ObjectId pero "foo" no es un ObjectId válido, por lo que el molde falla.

Esto no ocurre con 41224d776a326fb40f000001 porque esa cadena es un ObjectId válido.

Una forma de resolver esto es agregar un cheque antes de su llamada findById para ver si id es un ObjectId válido o no, así:

 if (id.match(/^[0-9a-fA-F]{24}$/)) { // Yes, it's a valid ObjectId, proceed with `findById` call. } 

Use las funciones existentes para verificar ObjectID.

 var mongoose = require('mongoose'); mongoose.Types.ObjectId.isValid('your id here'); 

¿Estás analizando esa cadena como ObjectId ?

Aquí en mi aplicación, lo que hago es:

 ObjectId.fromString( myObjectIdString ); 

También puede usar ObjectId.isValid de la siguiente manera:

 if (!ObjectId.isValid(userId)) return Error({ status: 422 }) 

Esta es una pregunta antigua pero también puede usar el paquete express-validator para verificar los parámetros de solicitud

express-validator versión 4 (última):

 validator = require('express-validator/check'); app.get('/show/:id', [ validator.param('id').isMongoId().trim() ], function(req, res) { // validation result var errors = validator.validationResult(req); // check if there are errors if ( !errors.isEmpty() ) { return res.send('404'); } // else model.findById(req.params.id, function(err, doc) { return res.send(doc); }); }); 

expreso-validador versión 3:

 var expressValidator = require('express-validator'); app.use(expressValidator(middlewareOptions)); app.get('/show/:id', function(req, res, next) { req.checkParams('id').isMongoId(); // validation result req.getValidationResult().then(function(result) { // check if there are errors if ( !result.isEmpty() ) { return res.send('404'); } // else model.findById(req.params.id, function(err, doc) { return res.send(doc); }); }); }); 
  if(mongoose.Types.ObjectId.isValid(userId.id)) { User.findById(userId.id,function (err, doc) { if(err) { reject(err); } else if(doc) { resolve({success:true,data:doc}); } else { reject({success:false,data:"no data exist for this id"}) } }); } else { reject({success:"false",data:"Please provide correct id"}); } 

lo mejor es verificar la validez

Fui con una adaptación de la solución @gustavohenke, implementando ObjectId de lanzamiento en un try-catch envuelto alrededor del código original para aprovechar la falla de la conversión de ObjectId como método de validación.

 Controller.prototype.show = function(id, res) { try { var _id = mongoose.Types.ObjectId.fromString(id); // the original code stays the same, with _id instead of id: this.model.findById(_id, function(err, doc) { if (err) { throw err; } if (!doc) { res.send(404); } return res.send(doc); }); } catch (err) { res.json(404, err); } }; 

O puedes hacer esto

var ObjectId = require('mongoose').Types.ObjectId; var objId = new ObjectId( (param.length < 12) ? "123456789012" : param );

como se menciona aquí, el método de búsqueda de Mongoose con $ o condición no funciona correctamente

Siempre use mongoose.Types.ObjectId('your id') para las condiciones en su consulta, validará el campo de ID antes de ejecutar su consulta, como resultado, su aplicación no se bloqueará.

Me enfrenté a este problema porque estaba declarando el enrutador como

 router.put('/:id', async (req, res) => { // code .... } 

y estaba actualizando los datos con url ie

 http://localhost:3000/id=5af584ebb62aae2fa8e406a2 

Después de pasar mucho tiempo, me corrijo quitando id= como

el camino correcto fue:

 http://localhost:3000/5af584ebb62aae2fa8e406a2 

Ahora puedo usar findById() como

 let myModel = await Model.findById(req.params.id); 

Tengo el mismo problema que agrego
_id: String .in schema then it start work