简体   繁体   中英

MongooseError - Operation `users.findOne()` buffering timed out after 10000ms

My code was working before initially but I don't know why it just stopped working and gave me this error:

MongooseError: Operation `users.findOne()` buffering timed out after 10000ms
    at Timeout.<anonymous> (/Users/nishant/Desktop/Yourfolio/backend/node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js:184:20)
    at listOnTimeout (internal/timers.js:549:17)
    at processTimers (internal/timers.js:492:7)

I am trying to authenticate the user by login with JWT. My client runs fine but in my backend I get this error. My backend code:

import neuron from '@yummyweb/neuronjs'
import bodyParser from 'body-parser'
import cors from 'cors'
import mongoose from 'mongoose'
import emailValidator from 'email-validator'
import passwordValidator from 'password-validator'
import User from './models/User.js'
import Portfolio from './models/Portfolio.js'
import bcrypt from 'bcryptjs'
import jwt from 'jsonwebtoken'
import auth from './utils/auth.js'

// Dot env
import dotenv from 'dotenv'
dotenv.config()

// Custom Password Specifications
// Username Schema
const usernameSchema = new passwordValidator()
usernameSchema.is().min(3).is().max(18).is().not().spaces()

// Password Schema
const passwordSchema = new passwordValidator()
passwordSchema.is().min(8).is().max(100).has().uppercase().has().lowercase().has().digits().is().not().spaces()

const PORT = process.env.PORT || 5000
const neuronjs = neuron()

// Middleware
neuronjs.use(bodyParser())
neuronjs.use(cors())

// Mongoose Connection
mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true }, () => console.log("MongoDB Connected"))

// API Routes
neuronjs.POST('/api/auth/signup', async (req, res) => {
    const { username, email, password, passwordConfirmation } = req.body

    // Validation: all fields are filled
    if (!username || !email || !password || !passwordConfirmation) {
        return res.status(400).json({ 
            "error": "true",
            "for": "fields",
            "msg": "fill all the fields"
        })
    }

    // Validation: username is valid
    if (usernameSchema.validate(username, { list: true }).length !== 0) {
        return res.status(400).json({ 
            "error": "true",
            "for": "username",
            "method_fail": usernameSchema.validate(username, { list: true }),
            "msg": "username is invalid"
        })
    }

    // Validation: email is valid
    if (!emailValidator.validate(email)) {
        return res.status(400).json({ 
            "error": "true",
            "for": "email",
            "msg": "email is invalid"
        })
    }

    // Validation: password is valid
    if (passwordSchema.validate(password, { list: true }).length !== 0) {
        return res.status(400).json({ 
            "error": "true",
            "for": "password",
            "method_fail": passwordSchema.validate(password, { list: true }),
            "msg": "password is invalid"
        })
    }

    // Validation: password is confirmed
    if (password !== passwordConfirmation) {
        return res.status(400).json({ 
            "error": "true",
            "for": "confirmation",
            "msg": "confirmation password needs to match password"
        })
    }

    // Check for existing user with email
    const existingUserWithEmail = await User.findOne({ email })
    if (existingUserWithEmail)
        return res.status(400).json({ "error": "true", "msg": "a user already exists with this email" })

    // Check for existing user with username
    const existingUserWithUsername = await User.findOne({ username })
    if (existingUserWithUsername)
        return res.status(400).json({ "error": "true", "msg": "a user already exists with this username" })

    // Generating salt
    const salt = bcrypt.genSalt()
    .then(salt => {
        // Hashing password with bcrypt
        const hashedPassword = bcrypt.hash(password, salt)
        .then(hash => {
            const newUser = new User({
                username,
                email,
                password: hash
            })
            // Saving the user
            newUser.save()
            .then(savedUser => {
                const newPortfolio = new Portfolio({
                    user: savedUser._id,
                    description: "",
                    socialMediaHandles: {
                        github: savedUser.username,
                        dribbble: savedUser.username,
                        twitter: savedUser.username,
                        devto: savedUser.username,
                        linkedin: savedUser.username,
                    }
                })

                // Save the portfolio
                newPortfolio.save()

                // Return the status code and the json
                return res.status(200).json({
                    savedUser
                })
            })
            .catch(err => console.log(err))
        })
        .catch(err => console.log(err))
    })
    .catch(err => console.log(err))
})

neuronjs.POST('/api/auth/login', async (req, res) => {
    try {
        const { username, password } = req.body

        // Validate
        if (!username || !password) {
            return res.status(400).json({ "error": "true", "msg": "fill all the fields", "for": "fields", })
        }

        const user = await User.findOne({ username })
        if (!user) {
            return res.status(400).json({ "error": "true", "msg": "no account is registered with this username", "for": "username" })
        }
    
        // Compare hashed password with plain text password
        const match = await bcrypt.compare(password, user.password)
    
        if (!match) {
            return res.status(400).json({ "error": "true", "msg": "invalid credentials", "for": "password" })
        }
    
        // Create JWT token
        const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET)
        return res.json({ token, user: { "id": user._id, "username": user.username, "email": user.email } })
    }
    catch (e) {
        console.log(e)
    }
})

// Delete a user and their portfolio
neuronjs.DELETE("/api/users/delete", async (req, res) => {
    auth(req, res)
    const deletedPortfolio = await Portfolio.findOneAndDelete({ user: req.user })
    const deletedUser = await User.findByIdAndDelete(req.user)
    res.json(deletedUser)
})

neuronjs.POST("/api/isTokenValid", async (req, res) => {
    const token = req.headers["x-auth-token"]
    if (!token) return res.json(false)
    
    const verifiedToken = jwt.verify(token, process.env.JWT_SECRET)
    if (!verifiedToken) return res.json(false)
    
    const user = await User.findById(verifiedToken.id)
    if (!user) return res.json(false)

    return res.json(true)
})

// Getting one user
neuronjs.GET("/api/users/user", async (req, res) => {
    auth(req, res)
    const user = await User.findById(req.user)
    res.json({
        "username": user.username,
        "email": user.email,
        "id": user._id
    })
})

// Getting the porfolio based on username
neuronjs.GET("/api/portfolio/:username", async (req, res) => {
    try {
        const existingUser = await User.findOne({ username: req.params.username })
        // User exists
        if (existingUser) {
            const userPortfolio = await Portfolio.findOne({ user: existingUser._id })
            return res.status(200).json(userPortfolio)
        }
        // User does not exist
        else return res.status(400).json({ "error": "true", "msg": "user does not exist" })
    }
    catch (e) {
        console.log(e)
        return res.status(400).json({ "error": "true", "msg": "user does not exist" })
    }
})

// Update Portfolio info
neuronjs.POST("/api/portfolio/update", async (req, res) => {
    auth(req, res)

    // Find the portfolio
    const portfolio = await Portfolio.findOne({ user: req.user })
    // Then, update the portfolio
    if (portfolio) {
        // Call the update method
        const updatedPortfolio = await portfolio.updateOne({
             user: req.user, 
             description: req.body.description, 
             socialMediaHandles: req.body.socialMediaHandles, 
             greetingText: req.body.greetingText, 
             navColor: req.body.navColor, 
             font: req.body.font, 
             backgroundColor: req.body.backgroundColor,
             rssFeed: req.body.rssFeed,
             displayName: req.body.displayName,
             layout: req.body.layout,
             occupation: req.body.occupation
            })
        return res.status(200).json(portfolio)
    }
})

neuronjs.listen(PORT, () => console.log("Server is running on port " + PORT))

The auth.js file function:

import jwt from 'jsonwebtoken'

const auth = (req, res) => {
    const token = req.headers["x-auth-token"]
    if (!token)
        return res.status(401).json({ "error": "true", "msg": "no authentication token" })
    
    const verifiedToken = jwt.verify(token, process.env.JWT_SECRET)
    if (!verifiedToken)
        return res.status(401).json({ "error": "true", "msg": "token failed" })
    
    req.user = verifiedToken.id
}

export default auth

Any help is much appreciated and I have already tried a few solutions like deleting node_modules and re installing mongoose.

In my experience this happens when your database is not connected, Try checking out following things -

  • Is you database connected and you are pointing to the same url from your code.
  • check if your mongoose.connect(...) code is loading.

I faced this issue where I was running the node index.js from my terminal and mongoose connect code was into different file. After requiring that mongoose code in index.js it was working again.

According to Documentation found in this link: https://mongoosejs.com/docs/connections.html#buffering

Mongoose lets you start using your models immediately, without waiting for mongoose to establish a connection to MongoDB.

That's because mongoose buffers model function calls internally. This buffering is convenient, but also a common source of confusion. Mongoose will not throw any errors by default if you use a model without connecting.

TL;DR:

Your model is being called before the connection is established. You need to use async/await with connect() or createConnection(); or use .then() , as these functions return promises now from Mongoose 5 .

I had the same issue when using Mongoose 6 . I connected to Mongoose in my index.js file the following way:

mongoose.connect(
  process.env.MONGO_URL,
  { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true },
  () => {
    console.log('Connected to MongoDB');
  }
);

I found the following info for Mongoose 6 in their site:

useNewUrlParser, useUnifiedTopology, useFindAndModify, and useCreateIndex are no longer supported options. Mongoose 6 always behaves as if useNewUrlParser, useUnifiedTopology, and useCreateIndex are true, and useFindAndModify is false. Please remove these options from your code.

When I removed the useCreateIndex: true option the issue was solved.

My code worked normaly from one PC but from another one I got the same error. I have MongoDB free hosting by https://www.mongodb.com/ .

I fixed it by adding my current IP to Security - Network Access - IP Access List in the hosting server.

I've run into this a number of times; particularly when I've upgraded nested dependancies that require mongoose. This always does the trick for me.

rm -rf node_modules
rm package-lock.json
npm install --package-lock-only
npm install

I think the reason is that your IP address is not whitelisted for your db. Check for it if you have a problem like this.

Allow Network Access from everywhere.

Please note that this is a temporary solution.

What this error is trying to say is that it cannot access the MongoDB collection. This may be mostly because of these 2:

  1. Your IP address is not allowed to access the database
  2. You don't have an internet connection

After Creating Cluster click connect and add your IP or add another IP in the MongoDB Atlas

This error[ user.findOne() ] showing because your config package version is updated automatically.

Enter the following in your terminal:

npm i -E config@3.3.1

or

yarn add -E config@3.3.1

I had the same problem. In my case, I had kept mongoose.connect statement in a different file and forgot to invoke it while writing the require statement.

require(./services/mongoose);

I had done this in my index.js file and changed it to this

require(./services/mongoose)();

well my problem solved since, There was already a Cluster, collection made in my mongo db atlas, all i had to do was clear that out and send another post request to make it work.

I just had this issue myself when I tried to use my database while my server was in error and mongoose created a huge 87 part error panel that I had to sift through and when I did, I found that the options that I passed to mongoose were depreciated. So if you can scroll to where you start your server, you may see details telling you to remove or append certain options. Removing the extra options fixed my issue. 我的问题的照片证据以及我在航站楼的哪里找到的

Make sure that you're connecting to MongoDB at the top of your function(inside file) and doing (CRUD) operations after connecting to MongoDB Atlas.

Hope that makes sense. I was getting error because in my file I'm loading data from other server and inserting into my MongoDB after that asynchronous operations I'm connecting to my MongoDB Server, that's why I was getting error.

CORRECT

-

await mongoose.connect(MONGO_URL, {
         useNewUrlParser: true,
         useUnifiedTopology: true,
       }); await parseAndLoadPlanetsData();

INCORRECT

-

await parseAndLoadPlanetsData();
       await mongoose.connect(MONGO_URL, {
         useNewUrlParser: true,
         useUnifiedTopology: true,
       });

It worked for me after I used this code, in my app.js file:

mongoose.connect(process.env.DATABASE_URI, () => {
    console.log("Mongo connected");
});

And removed all the four mongoose options below from my code:

{
    useNewUrlParser: true,
    useUnifiedTopology: true,
    useCreateIndex: true,
    useFindAndModify: false,  
}

The first identification here is MongoDB connection is not successful due to connection timeout. This is due to many possibilities but for my case is MongoBD Connection URI is wrong.

Error:

mongodb://admin:admin123@mongo:27017

mongoose
  .connect("mongodb://admin:admin123@mongo:27017", { useNewUrlParser: true })
  .then(() =>
    console.log(`${chalk.green('✓')} ${chalk.blue('MongoDB Connected!')}`)
  )
  .catch(err => console.log(err));

Solution:

mongodb://localhost:27017/test

mongoose
  .connect("mongodb://localhost:27017/test", { useNewUrlParser: true })
  .then(() =>
    console.log(`${chalk.green('✓')} ${chalk.blue('MongoDB Connected!')}`)
  )
  .catch(err => console.log(err));

If you are trying to run the project from another network or Ip, make sure you whitelist your ip in mongoDB atlas. Simply go to Network tab> Add ip address.

mongoose.connect('mongodb://localhost/myapp', {useNewUrlParser: true});

Just do this add {useNewUrlParser: true} in connection file.

I had this problem because I tried to use shared model between two node applications, after I copied the model within my application it worked.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM