186 votes

Quelle est l'erreur Mongoose Cast to ObjectId failed for value XXX at path "_id" ?

Lorsque vous envoyez une demande à /customers/41224d776a326fb40f000001 et un document avec _id 41224d776a326fb40f000001 n'existe pas, doc es null et je renvoie 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);
    });
  };

Cependant, lorsque _id ne correspond pas à ce que Mongoose attend comme "format" (je suppose) par exemple avec GET /customers/foo une erreur étrange est renvoyée :

CastError : Cast to ObjectId failed for value "foo" at path "_id".

Alors, c'est quoi cette erreur ?

3voto

Ze Rubeus Points 3760

Vous pouvez également utiliser ObjectId.isValid comme suit :

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

3voto

Manil Malla Points 69

Si les solutions ci-dessus ne fonctionnent pas pour vous. Vérifiez si vous envoyez un GET à une POST route.
C'était aussi simple et stupide pour moi.

2voto

Erons Points 21

J'ai été confronté à quelque chose de similaire récemment et je l'ai résolu en attrapant l'erreur pour savoir si c'est une erreur Mongoose ObjectId.

app.get("/:userId", (req, res, next) => {
    try {
        // query and other code here
    } catch (err) {
        if (err.kind === "ObjectId") {
            return res.status(404).json({
                errors: [
                    {
                        msg: "User not found",
                        status: "404",
                    },
                ],
            });
        }
        next(err);
    }
});

2voto

Denis Pshenov Points 1300

Vous pouvez soit valider chaque ID avant de l'utiliser dans vos requêtes (ce qui, à mon avis, est la meilleure pratique),

// Assuming you are using Express, this can return 404 automatically.
app.post('/resource/:id([0-9a-f]{24})', function(req, res){
  const id = req.params.id;
  // ...
});

... ou vous pouvez patcher Mongoose pour qu'il ignore ces erreurs d'encodage et utilise à la place une représentation en chaîne pour poursuivre la requête. Bien entendu, votre requête ne trouvera rien, mais c'est probablement ce que vous souhaitez de toute façon.

import { SchemaType }  from 'mongoose';

let patched = false;

export const queryObjectIdCastErrorHandler = {
  install,
};

/**
 * Monkey patches `mongoose.SchemaType.prototype.castForQueryWrapper` to catch
 * ObjectId cast errors and return string instead so that the query can continue
 * the execution. Since failed casts will now use a string instead of ObjectId
 * your queries will not find what they are looking for and may actually find
 * something else if you happen to have a document with this id using string
 * representation. I think this is more or less how MySQL would behave if you
 * queried a document by id and sent a string instead of a number for example.
 */
function install() {
  if (patched) {
    return;
  }

  patch();

  patched = true;
}

function patch() {
  // @ts-ignore using private api.
  const original = SchemaType.prototype.castForQueryWrapper;

  // @ts-ignore using private api.
  SchemaType.prototype.castForQueryWrapper = function () {
    try {
      return original.apply(this, arguments);
    } catch (e) {
      if ((e.message as string).startsWith('Cast to ObjectId failed')) {
        return arguments[0].val;
      }

      throw e;
    }
  };
}

2voto

Iheb Saad Points 81

Tout ce que vous avez à faire est de changer le nom du paramètre "id" en "_id".

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X