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?
CodePudding user response:
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
}
}
CodePudding user response:
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
.