Getting “MongooseServerSelectionError: connect ECONNREFUSED”, “bad auth”, “buffering timed out” or an Atlas IP whitelist error when your Node.js app tries to reach MongoDB? This guide helps you read the message and shows 6 fixes for local MongoDB, MongoDB Atlas and Docker, with working code.
Your Express API starts, but the first database call fails, or the app crashes right away with one of these messages:
MongooseServerSelectionError: connect ECONNREFUSED 127.0.0.1:27017MongooseServerSelectionError: Could not connect to any servers in your MongoDB Atlas cluster.MongoServerError: bad auth : Authentication failed.Error: querySrv ENOTFOUND _mongodb._tcp.cluster0.xxxxx.mongodb.netMongooseError: Operation `users.find()` buffering timed out after 10000ms
All of them mean “the app could not talk to the database,” but the causes are very different. The message tells you where to look, so start by matching yours in the table below.
Step 1: Match the Message to the Cause
| Message | Usual cause | Go to |
|---|---|---|
connect ECONNREFUSED 127.0.0.1:27017 | Local MongoDB is not running or not listening on that address | Step 2 |
connect ECONNREFUSED ::1:27017 | localhost resolved to IPv6, but MongoDB listens on IPv4 | Step 2 |
Could not connect to any servers in your MongoDB Atlas cluster | Your IP is not on the Atlas IP Access List, or the cluster is paused | Step 3 |
bad auth : Authentication failed | Wrong user, password or authentication database | Step 4 |
querySrv ENOTFOUND or querySrv ECONNREFUSED | DNS problem with a mongodb+srv:// string, or a typo in the host | Step 5 |
uri parameter ... got "undefined" | The environment variable with the connection string was not loaded | Step 5 |
| Works on your laptop, fails in Docker | localhost points to the container itself | Step 6 |
buffering timed out after 10000ms | Models were used before a successful connection | Step 7 |
Step 2: Local MongoDB, Start It and Use 127.0.0.1
ECONNREFUSED on port 27017 usually means nothing is listening there. Start MongoDB first.
Linux (systemd):
sudo systemctl start mongodsudo systemctl status mongod
macOS with Homebrew:
brew services start mongodb-community
Windows: start the MongoDB Server service from the Services app. Or run MongoDB in Docker:
docker run -d -p 27017:27017 --name mongo mongo:7
Then confirm you can connect from the terminal. If this fails too, the problem is MongoDB itself, not your Node.js code:
mongosh "mongodb://127.0.0.1:27017"
If ECONNREFUSED shows ::1, it is an IPv6 problem. Newer Node.js versions can resolve localhost to the IPv6 address, while MongoDB listens on IPv4 only. The simple fix is to write the IPv4 address in your connection string:
mongodb://127.0.0.1:27017/mydb
Step 3: MongoDB Atlas, IP Access List and Paused Clusters
If you see the message about not being able to reach servers in your Atlas cluster, the most common reason is that Atlas blocks every IP address that is not on its allow list. In the Atlas dashboard:
- Open Network Access (under Security).
- Click Add IP Address and choose Add Current IP Address.
- Wait until the status becomes Active, then run your app again.
Your home or office IP can change, so this fix may stop working later. Entering 0.0.0.0/0 allows every address. It is useful for a quick test, but it is not safe for a real project, so replace it with specific addresses afterwards.
Also check these two things:
- Free-tier clusters can be paused after a long period of inactivity. If the cluster shows as paused, resume it in the dashboard.
- Cloud hosts such as Render, Vercel or serverless platforms may use changing outbound IP addresses. Check your host’s documentation for fixed outbound IPs or private networking options before relying on a small allow list.
Step 4: Fix “bad auth : Authentication failed”
This message means MongoDB reached you but refused your login. Check these causes in order:
- Wrong database user or password. In Atlas, the database user (under Database Access) is different from your Atlas website login.
- Special characters in the password. Characters like
@,:,/and#break the connection string unless they are URL-encoded. - Wrong authentication database. For a self-hosted MongoDB where the user was created in the
admindatabase, addauthSource=adminto the connection string.
Build the string safely in code so special characters are encoded for you:
const user = encodeURIComponent(process.env.DB_USER);const pass = encodeURIComponent(process.env.DB_PASS);
const uri = `mongodb+srv://${user}:${pass}@cluster0.xxxxx.mongodb.net/mydb?retryWrites=true&w=majority`;
For a self-hosted server, the string looks like this:
mongodb://myUser:myPassword@127.0.0.1:27017/mydb?authSource=admin
Step 5: Fix the Connection String and Environment Variable
Two separate problems show up here.
The variable is undefined. If you see got "undefined", your .env file was never loaded. Load it before you read any variable:
require('dotenv').config();
console.log(process.env.MONGODB_URI ? 'URI loaded' : 'URI missing');
Do not print the URI itself, because it contains your password. On Node.js 20.6 and newer you can also load the file without a package:
node --env-file=.env server.js
The SRV lookup fails. A mongodb+srv:// string needs a DNS lookup, and querySrv ENOTFOUND means that lookup failed. Check the host name for typos first. If it is correct, your network, VPN or DNS server may be blocking the lookup. You can test with a different DNS server in your app:
const dns = require('dns');dns.setServers(['8.8.8.8', '1.1.1.1']);
Place this before you call mongoose.connect. If it helps, fix your system DNS rather than keeping the workaround. Atlas also lets you copy a standard mongodb:// connection string, which avoids the SRV lookup completely.
Step 6: Fix Docker and Docker Compose
Inside a container, localhost means the container itself, not your laptop and not another container. In Docker Compose, use the service name as the host:
services: api: build: . environment: MONGODB_URI: mongodb://mongo:27017/mydb depends_on: - mongo
mongo: image: mongo:7 volumes: - mongo-data:/data/db
volumes: mongo-data:
The depends_on setting only controls start order, it does not wait until MongoDB is ready. That is why the connection code in Step 7 should fail clearly, or retry, instead of continuing silently.
Step 7: Connect First, Then Use Your Models
The message buffering timed out after 10000ms appears because Mongoose queues database commands while it waits for a connection. If the connection never succeeds, or you start the server before it finishes, those commands time out. Connect first, handle the error, and only then start listening:
require('dotenv').config();const mongoose = require('mongoose');const app = require('./app');
async function start() { try { await mongoose.connect(process.env.MONGODB_URI, { serverSelectionTimeoutMS: 5000 }); console.log('MongoDB connected');
app.listen(3000, () => console.log('API running on port 3000')); } catch (err) { console.error('MongoDB connection failed:', err.message); process.exit(1); }}
start();
The serverSelectionTimeoutMS option makes Mongoose give up after 5 seconds instead of the default 30, so you see the real error faster. Older tutorials add options like useNewUrlParser and useUnifiedTopology. Current Mongoose versions do not need them.
Security Notes
- Never put your connection string in your code or your Git repository. Keep it in an environment variable, and add
.envto.gitignore. - Avoid
0.0.0.0/0in Atlas for anything beyond a short test. - Create a separate database user for each app, with only the permissions it needs.
- Do not log the full connection string, since it contains the password.
Debug Checklist
- Read the exact error message and match it in Step 1.
- Try to connect with
mongoshfrom the same machine or container. If that fails, fix the network or MongoDB first. - Check that your environment variable is loaded, without printing the secret.
- For Atlas, confirm your current IP is on the Access List and the cluster is running.
- Make sure you connect before you start the server or use any model.
Conclusion
MongoDB connection errors look scary, but each message points to one layer: the server is not running, the network blocks you, the login is wrong, the connection string is broken, or your code uses the database too early. Match the message, test with mongosh, and fix that layer first. With a clean startup function like the one in Step 7, future problems show up clearly instead of as mysterious timeouts.

0 Comments