Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose: Defining 404 status for not finding a document doesnt work

I,m learning MongoDB and mongoose and now I have a problem in defining a 404 status for my route handler. Here is the code:

app.get('/users/:id', async (req, res) => {
const _id = req.params.id

try {
    const user = await User.findById(_id)
    if (!user) {
        return res.status(404).send()
    }
    res.send(user)
} catch (error) {
    res.status(500).send()
}

})

Now if I give it an id that doesn't exist, it doesn't give me 404 Not Found status. it only executes the catch block which is not what I want. I would appreciate it if you tell me where I made mistake or tell me a way to get error handling for that. Thanks

like image 441
Ali Raisi Avatar asked Dec 13 '25 02:12

Ali Raisi


1 Answers

The problem

As you can see in the log

CastError: Cast to ObjectId failed for value "6082d50a2c89db3164" at path "_id" for model "User"

It means : the value you provide to findById function ("6082d50a2c89db3164") is not a valid ObjectId.Then the catch block is executed.

Suggestion

1. Validate the parameter before query in database

I understand that you're trying to provide some id that doesn't exist in the database to test. But IMHO, there a difference between 2 cases :

  • you provide a valid id, and this id cannot be found in the database. It should return 404 in this case
  • you provide an invalid id in the request, it could be a string like "6082d50a2c89db3164", or even "#Q*&$(#@*" or anything we could imagine. For this case, it could be better if we validate the input (req.params._id) to ensure that the format is valid. The code will be something like this:
app.get('/users/:id', async (req, res) => {
const _id = req.params.id;

// validate params
if(!isValidateObjectId(_id)) { // the function we need to write
   res.status(200).send("Invalid params"); // you can define your status and message
   return;
}

// good params, get user from database
try {
    const user = await User.findById(_id)
    if (!user) {
        return res.status(404).send()
    }
    res.send(user)
} catch (error) {
    res.status(500).send()
}
})

2. Use findOne() method instead of findById

If you want a simpler solution, don't use findById because the function expects a valid ObjectId. We can use findOne() method :

app.get('/users/:id', async (req, res) => {
const _id = req.params.id

try {
    const user = await User.findOne({_id : _id})
    if (!user) {
        return res.status(404).send()
    }
    res.send(user)
} catch (error) {
    res.status(500).send()
}
})

(IMHO, the first solution is better though..)

Some helpful link :

  • https://docs.mongodb.com/manual/reference/method/ObjectId/
  • Can I determine if a string is a MongoDB ObjectID?
  • https://mongoosejs.com/docs/api.html#model_Model.findOne
like image 100
Đăng Khoa Đinh Avatar answered Dec 14 '25 14:12

Đăng Khoa Đinh



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!