Learning objectives
After reading this article you will be able to:
- Read a MongoServerSelectionError message and know what each part points to
- Find the cause with a short script, mongosh and network checks
- Fix host, firewall, IP access list, DNS, TLS and replica set problems
You start your app, it hangs for a few seconds and then dies with MongoServerSelectionError. The name sounds alarming, but the message says something simple: the driver looked for a MongoDB server to talk to and found none that answered in time. The connection never started, so tweaking queries, indexes or schemas will not help.
The examples below use the official mongodb driver for Node.js and also apply to Mongoose, which runs on top of that driver. If you are still setting up the connection from scratch, start with how to connect MongoDB to Node.js.
What does the error look like?#
The text after the colon is what matters. These are real messages from the driver:
MongoServerSelectionError: connect ECONNREFUSED 127.0.0.1:27017
MongoServerSelectionError: connect ECONNREFUSED ::1:27017, connect ECONNREFUSED 127.0.0.1:27017
MongoServerSelectionError: getaddrinfo ENOTFOUND db.example.internal
MongoServerSelectionError: Server selection timed out after 30000 msEach one points somewhere different:
ECONNREFUSED: the address exists, but nothing accepted the connection on that port. The server is down, listens on another interface, or you are on the wrong host.ENOTFOUND: the hostname did not resolve in DNS. A typo, an internal name that only exists on another network, or an environment variable with a stale value.Server selection timed out: packets went out and nothing came back. That is the signature of a firewall, an IP access list or an unreachable address.
In Mongoose the error is called MongooseServerSelectionError. When the target is a MongoDB Atlas cluster and no server answers, Mongoose replaces the message with this one:
MongooseServerSelectionError: Could not connect to any servers in your MongoDB Atlas cluster. One common reason is that you're trying to access the database from an IP that isn't whitelisted. Make sure your current IP address is on your Atlas cluster's IP whitelist: https://www.mongodb.com/docs/atlas/security-whitelist/In Python, the PyMongo equivalent is pymongo.errors.ServerSelectionTimeoutError, with a topology description at the end of the message.
What does the driver try before giving up?#
The driver does not just open one connection. It reads the host list from the connection string, resolves each name in DNS, opens TCP (and TLS, if enabled) to each host and asks the server for its role: primary, secondary or standalone. Only then does it pick a suitable server for the operation. That process is server selection.
If no host qualifies within serverSelectionTimeoutMS, the operation fails. The default is 30000 ms, which is why the error often shows up half a minute later. Replica sets add one more rule: the hostnames in the connection string must match the ones in the replica set configuration, and the driver must be able to reach the members by those names. The terms are explained in collections, clusters and replica sets.
Two practical consequences: the error says little about the database itself, and a shorter deadline speeds up debugging. With serverSelectionTimeoutMS: 5000, you wait 5 seconds instead of 30 on every attempt.
How do you find the cause?#
Start with the driver itself. The error carries the topology it saw in reason, with the state of each host. This script prints all of it:
// diagnose.mjs
import { MongoClient } from "mongodb";
const uri = process.env.MONGODB_URI;
if (!uri) throw new Error("Set the MONGODB_URI variable");
const client = new MongoClient(uri, { serverSelectionTimeoutMS: 5000 });
try {
await client.db("admin").command({ ping: 1 });
console.log("Connected: the server answered the ping");
} catch (error) {
console.error(`${error.name}: ${error.message}`);
// error.reason describes the topology the driver saw
console.error("Topology:", error.reason?.type);
for (const [host, server] of error.reason?.servers ?? []) {
console.error(`- ${host}: ${server.type} ${server.error?.message ?? ""}`);
}
process.exitCode = 1;
} finally {
await client.close();
}Run it with MONGODB_URI="mongodb://..." node diagnose.mjs on the same machine where the app fails. A ReplicaSetNoPrimary topology (or Unknown, when the string has a single host) with every host Unknown means no server answered.
Then separate network problems from app problems with tools outside Node.js. The three commands below answer, in order: does the name resolve? Is the port open from this machine? Does the server answer with the same string?
nslookup db.example.com
nc -vz db.example.com 27017
mongosh "$MONGODB_URI" --eval "db.runCommand({ ping: 1 })"On Windows PowerShell, Test-NetConnection db.example.com -Port 27017 replaces nc. If mongosh fails too, the problem is not in your code.
Why do you get ECONNREFUSED?#
From most to least common:
- The string points to localhost outside your computer. Your PC had a local MongoDB; on the server or inside a container,
localhostis that machine, and there is no database there. This is the classic "works locally, fails in production" case. Also check for a fallback such asprocess.env.MONGODB_URI || "mongodb://localhost:27017": if the variable is missing, the code silently falls back to localhost. See what environment variables are. - The server is down. Check the
mongodprocess or the database container and read its log. - The server only listens on localhost. By default
mongodaccepts connections on localhost only. To reach it from another machine, it must listen on the right network interface (net.bindIp), ideally the private one, behind a firewall and with authentication on. - IPv6 versus IPv4. On recent Node.js versions,
localhostmay resolve to::1first, and Node tries both addresses, which is why the message lists::1and127.0.0.1. If the database only listens on IPv4, use127.0.0.1in the string or thefamily: 4option.
A refused connection works the same way for other databases: see database connection refused.
Why does server selection time out?#
A timeout means nobody answered, not even to refuse. Typical causes:
- The provider's IP access list. MongoDB Atlas only accepts connections from addresses on the project's access list. Add the public IP your app connects from. Home IPs change over time, so access that worked yesterday can stop today.
- A firewall. The port (27017 by default) is closed on the database server, in the cloud security group or on your app's outbound network. Open only the database port, and only to what needs it.
- A replica set with internal names. The driver connects to the first host, receives a member list with names that only exist inside the database network (such as container names) and cannot reach them. The topology stays
ReplicaSetNoPrimary. Fix the names in the replica set configuration or, to test a single member, usedirectConnection=true. - Mismatched TLS. If the server requires TLS and the client does not use it (or the other way around), the handshake never completes and the driver may wait until the deadline. See the next section.
What if the error involves DNS or TLS?#
mongodb+srv:// strings do not list hosts. The driver looks up an SRV record and a TXT record in DNS to find the servers and options. When that lookup fails, the error shows up before server selection, with a different message:
Error: querySrv ENOTFOUND _mongodb._tcp.cluster0.example.mongodb.netCheck the cluster name you copied from the provider and test the lookup with nslookup -type=SRV _mongodb._tcp.cluster0.example.mongodb.net. Some ISP and VPN resolvers fail on SRV records; switching the machine's resolver often fixes it. To see how the lookup works, read what DNS is.
With mongodb+srv://, TLS is turned on automatically. With mongodb://, it is off by default (tls=false), so add tls=true if the server requires it. Servers with their own certificate need tlsCAFile pointing to the certificate authority file. In Mongoose, a message that mentions SSL points to exactly this mismatch. The basics of certificates are in what SSL/TLS is.
How do you keep it from coming back?#
- Fail fast. Send a
pingat startup and exit with a clear message if it fails, instead of letting every request wait 30 seconds. - Validate the variable. Stop the app if
MONGODB_URIis empty, with no localhost fallback. - Use a single client. One
MongoClientper process, reused everywhere. A new client per request exhausts connections and causes other errors, such as too many connections. - Do not open the database to the world. Allowing
0.0.0.0/0makes the error go away but exposes the database to every address. Prefer a private network or your app's outbound IP.
How to do this on Square Cloud#
Square Cloud offers MongoDB hosting starting on the Standard plan (Hobby does not include databases). The database is ready in seconds, in the same datacenter as your apps, with an average latency of about 1 ms. It is a single node (standalone, no replica set) and it requires TLS. Those two details explain this error most often here.
To avoid the most common causes:
- Copy the full connection URL the dashboard hands you and do not add
replicaSet: on a single node, that parameter makes the driver wait for a primary that does not exist. - Download the certificate in the dashboard and pass
tls: true,tlsCAFilewith the CA andtlsCertificateKeyFilewith the.pem, because the client also presents the certificate. - Set
MONGODB_URIas an environment variable of the app, in the dashboard, the API, the CLI or VS Code. The change applies on the next restart, so restart the app after editing the variable. - Use a single
MongoClientin your code, with no localhost fallback, and run the diagnostic script above. The database accepts connections from outside, so the script also runs on your machine.
If your app uses a MongoDB from another provider with an IP access list, remember it connects out over a dynamic IPv4 address, with no fixed IP to allow. To recover data, you take manual snapshots whenever you want, and every plan that includes databases also has a daily automatic snapshot. You can restore a snapshot into the same database, another one of the same engine or a new database. See the details on MongoDB hosting.
Database hosting
MongoDB, PostgreSQL, MySQL and Redis next to your app
FAQs
What is MongoServerSelectionError?
It is the error the MongoDB driver throws when it cannot pick a server for an operation within serverSelectionTimeoutMS. It means the connection never happened, so the problem is the network, the address or the server.
Why does the error take 30 seconds to show up?
Because serverSelectionTimeoutMS defaults to 30000 ms. The driver keeps trying to discover servers for that long and only gives up at the end. You can lower the value so the error appears sooner.
It works on my machine but not on the server. Why?
Almost always the connection string points to localhost, or the environment variable was never set on the server. On another machine, localhost is that machine itself, where no MongoDB is running.
Does allowing 0.0.0.0/0 in MongoDB Atlas fix it?
It removes the IP block, but the cluster then accepts connections from any address, protected only by username and password. Allow just the outbound IP of the server where your app runs instead.
Can a wrong password cause MongoServerSelectionError?
Usually not. A wrong username or password tends to produce a MongoServerError with Authentication failed. If you get a server selection error, look at the network, the address or DNS first.
More in Databases
See all 24 articles- How much does database hosting cost?Cloud database hosting costs from zero to hundreds of dollars a month. See what sets the price: instance, disk, traffic, snapshots, and how to estimate yours.
- How to host a database for your appTo host a database, pick an engine, create the instance, store the connection string in an environment variable and test the connection. Step-by-step guide.
- What is Redis used for?Redis is an in-memory data store that keeps key-value pairs and rich data structures. Learn how it works, what it is used for and when not to use it.
- How to back up your databaseBack up MySQL, PostgreSQL and MongoDB with mysqldump, pg_dump and mongodump, then restore the dump. See the commands, how to verify and common mistakes.