skip to Main Content

I have a model called Product:

class Product {
    constructor(title, price, description, imageUrl) {
        this.title = title;
        this.price = price;
        this.description = description;
        this.imageUrl = imageUrl;
    }
    
    save() {
        const db = getDb();
        return db.collection("products").insertOne(this)
        .catch(error => dbDebugger(error));
    }
    
    static fetchById(productId) {
        const db = getDb();
        return db.collection("products").findOne({ _id: new ObjectId(productId) })
        .catch(error => dbDebugger(error.message));
    }

}

and in one of my controllers i tried to find the product with the productId which will come from the url as a url parameter:

exports.getSingleProduct = (req, res) => {
    const productId = req.params.id;
    
    Product.fetchById(productId)
    .then(product => {
        if(!product) {
            return res.redirect("404");
        }
        res.render("product-detail", { product, pageTitle: "Product Detail" });
    })
    .catch(error => dbDebugger(error));
};

and indeed everything work without no issue.
but once i change the productId from url(like appending one letter to it), i’ll see an error (even though i should be able to handle it in my controller).

BSONTypeError: Argument passed in must be a string of 12 bytes or a string of 24 hex characters or an integer

I think the error is coming from my model once i tried to convert it to ObjectId, if it is how can i fix that? and if its not then where that error is coming from?

2

Answers


  1. Your error occurs before any async code starts and .catch() is only used for handling rejected promises.

    I would recommend using async functions instead which will treat synchronous and asynchronous failures the same way

    static async fetchById(productId) {
      const db = getDb();
      try {
        return await db.collection("products")
          .findOne({ _id: new ObjectId(productId) });
      } catch (error) {
        dbDebugger(error.message);
        throw error; // don't forget to keep the promise rejection going
      }
    }
    
    Login or Signup to reply.
  2. This error happens when you’re trying to cast a none valid value into the ObjectId, I am not familiar with mongoose fetchById, I’m assuming it’s a custom function you or your team wrote where you cast the _id into ObjectId,

    My guess the code looks a little like this:

    fetchById(id){
      return this.model.findOne({_id: new ObjectId(id)})
    }
    

    This is why when you manually corrupt the objectid string it becomes a none valid objectid, and when the casting happens it throws an error. I would personally recommend adding validation to the REST route to make sure the param.id is actually a valid ObjectId.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search