skip to Main Content

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.

17

Answers


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

    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
  3. 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.

    Login or Signup to reply.
  4. mongoose.connect('mongodb://localhost/myapp', {useNewUrlParser: true});

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

    Login or Signup to reply.
  5. This error[user.findOne()] showing because your config package version is updated automatically.

    Enter the following in your terminal:

    npm i -E [email protected]
    

    or

    yarn add -E [email protected]
    
    Login or Signup to reply.
  6. 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
    
    Login or Signup to reply.
  7. 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.

    Login or Signup to reply.
  8. 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)();
    
    Login or Signup to reply.
  9. 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 .

    Login or Signup to reply.
  10. 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.

    Login or Signup to reply.
  11. 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.Photographic evidence of my issue and where I found it in the terminal

    Login or Signup to reply.
  12. 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,
    });
    
    Login or Signup to reply.
  13. 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.

    Login or Signup to reply.
  14. 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,  
    }
    
    Login or Signup to reply.
  15. 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.

    Login or Signup to reply.
  16. 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
    Login or Signup to reply.
  17. If you are importing the database connect string from .env file, make sure that the .env file is in the root folder where you are running the npm run command.

    I’ve tried all the solutions here to no awail. Suddenly I realized that the .env file was in /server folder, which is one folder deeper than my project root folder.

    Make sure you move .env file to project root folder!! To get the process.env.DB_CONNECT for example.

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