MongooseError: Query was already executed: user.findOneAndUpdate(

Issue

I’m following a tutorial online but i’ve an error that the teacher doesn’t have in the video (i also copy his code but same error).

I have this error only with the "PATCH" function (followUser) but the strange thing is that it updates well in mongoDB. It just gives me an error.

Here’s my code: user.controller.js

const ObjectID = require('mongoose').Types.ObjectId


module.exports.getAllUsers = async (req, res) => {
    try {
        const users = await userModel.find().select('-password')
        res.status(200).json(users)

    } catch (error) {
        throw error
    }
}

module.exports.getUserInfos = (req, res) => {
    if (!ObjectID.isValid(req.params.id)) {
        return res.status(400).send("ID unknow : " + req.params.id)
    }
    userModel.findById(req.params.id, (err, docs) => {
        if (!err) {
            res.send(docs)
        } else {
            console.log("ID unknow : " + err);
        }
    }).select('-password')
}

module.exports.updateUser = async (req, res) => {
    if (!ObjectID.isValid(req.params.id))
        return res.status(400).send("ID invalid : " + req.params.id);

    try {
        await userModel.findOneAndUpdate(
            { _id: req.params.id },
            {
                $set: {
                    bio: req.body.bio,
                },
            },
            { new: true, upsert: true, setDefaultsOnInsert: true }
        )
            .then((docs) => res.send(docs))
            .catch((err) => res.status(500).send({ message: err }));
    } catch (err) {
        res.status(500).json({ message: err });
    }
};

module.exports.deleteUser = (req, res) => {
    if (!ObjectID.isValid(req.params.id))
        return res.status(400).send("ID invalid : " + req.params.id);
    try {
        userModel.remove({ _id: req.params.id }).exec();
        res.status(200).json({ message: "Successfully deleted" })
    } catch (error) {
        return res.status(500).json({ message: error })
    }
}

module.exports.followUser = async (req, res) => {
    if (!ObjectID.isValid(req.params.id) || !ObjectID.isValid(req.body.idToFollow))
        return res.status(400).send("ID invalid : " + req.params.id);
    try {
        // add to the follower list
        await userModel.findByIdAndUpdate(
            req.params.id,
            { $addToSet: { following: req.body.idToFollow } },
            { new: true, upsert: true },
        );

        (err, docs) => {
            if (!err) res.status(201).json(docs);
            else return res.status(400).json(err);
        }
        // add to following list
        await userModel.findByIdAndUpdate(
            req.body.idToFollow,
            { $addToSet: { followers: req.params.id } },
            { new: true, upsert: true },
            (err, docs) => {
                // if (!err) res.status(201).json(docs);
                if (err) return res.status(400).json(err);
            }
        );
    } catch (err) {
        res.status(500).json({ message: err });
        throw err;
    }
}

module.exports.unfollowUser = async (req, res) => {
    if (!ObjectID.isValid(req.params.id))
        return res.status(400).send("ID invalid : " + req.params.id);
    try {

    } catch (error) {
        return res.status(500).json({ message: error })
    }
}

Here’s UserModel code :

const bcrypt = require("bcrypt")
const { isEmail } = require("validator")

const userSchema = new mongoose.Schema(
    {
        pseudo: {
            type: String,
            required: true,
            minLenght: 3,
            maxLength: 55,
            unique: true,
            trim: true
        },
        email: {
            type: String,
            required: true,
            lowercase: true,
            trim: true,
            validate: [isEmail]
        },
        password: {
            type: String,
            required: true,
            max: 1024,
            minLenght: 6
        },
        bio: {
            type: String,
            max: 1024
        },
        picture: {
            type: String,
            default: "./uploads/profil/random-user.png"
        },
        followers: {
            type: [String]
        },
        following: {
            type: [String]
        },
        likes: {
            type: [String]
        },
    },
    {
        timestamps: true
    }
)

// Play function before save into DB
userSchema.pre("save", async function (next) {
    const salt = bcrypt.genSalt();
    this.password = await bcrypt.hash(this.password, parseInt(salt))
    next();
})

const UserModel = mongoose.model('user', userSchema)

module.exports = UserModel;

Here the error in terminal:

    at model.Query._wrappedThunk [as _findOneAndUpdate] (/Users/gregorycorin/Desktop/Own_project/social_media_mern/node_modules/mongoose/lib/helpers/query/wrapThunk.js:21:19)
    at /Users/gregorycorin/Desktop/Own_project/social_media_mern/node_modules/kareem/index.js:334:18
    at _next (/Users/gregorycorin/Desktop/Own_project/social_media_mern/node_modules/kareem/index.js:128:16)
    at /Users/gregorycorin/Desktop/Own_project/social_media_mern/node_modules/kareem/index.js:555:30
    at processTicksAndRejections (internal/process/task_queues.js:75:11)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:7997) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:7997) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

And here the error in PostMan:

    "message": {
        "originalStack": "Error\n    at model.Query._wrappedThunk [as _findOneAndUpdate] (/Users/gregorycorin/Desktop/Own_project/social_media_mern/node_modules/mongoose/lib/helpers/query/wrapThunk.js:25:28)\n    at /Users/gregorycorin/Desktop/Own_project/social_media_mern/node_modules/kareem/index.js:334:18\n    at _next (/Users/gregorycorin/Desktop/Own_project/social_media_mern/node_modules/kareem/index.js:128:16)\n    at /Users/gregorycorin/Desktop/Own_project/social_media_mern/node_modules/kareem/index.js:555:30\n    at processTicksAndRejections (internal/process/task_queues.js:75:11)"
    }
}

Thanking you in advance.

Solution

Try doing it like this.

    module.exports.followUser = async (req, res) => {
        if (!ObjectID.isValid(req.params.id) || !ObjectID.isValid(req.body.idToFollow))
            return res.status(400).send("ID invalid : " + req.params.id);
        try {
    
            const update = {
                $addToSet: {
                    following: req.body.idToFollow,
                },
            };
            const options = {
                new: true,
                upsert: true,
            };
            let user = await userModel.findByIdAndUpdate(req.params.id, update, options).lean().exec();
            update['$addToSet'] = {
                followers: req.params.id
            };
            await userModel.findByIdAndUpdate(req.body.idToFollow, update, options).lean().exec();
    
            return res.status(201).json(user);
    
        } catch (err) {
            res.status(500).json({ message: err });
            throw err;
        }
    }

Answered By – Muhammad Usama

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published