MongoServerSelectionError: why MongoDB won't connect

MongoServerSelectionError means the driver found no available MongoDB server within its deadline, 30 seconds by default. The usual causes are a wrong host, a stopped server, a firewall or IP access list, and DNS.

Updated 7 min read

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
On this page

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.

serverSelectionTimeoutMSReads the stringlist of hosts1Resolves DNSeach name2ENOTFOUNDname does not resolveOpens TCP and TLSto each host3ECONNREFUSEDor a silent firewallAsks for the roleprimary or secondary4ReplicaSetNoPrimaryinternal host namesMongoServerSelectionErrorno host was usable in time
The error means no host got through every step before the deadline; the step that failed points to the cause.

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 ms

Each 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:

javascript
// 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?

bash
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:

  1. The string points to localhost outside your computer. Your PC had a local MongoDB; on the server or inside a container, localhost is that machine, and there is no database there. This is the classic "works locally, fails in production" case. Also check for a fallback such as process.env.MONGODB_URI || "mongodb://localhost:27017": if the variable is missing, the code silently falls back to localhost. See what environment variables are.
  2. The server is down. Check the mongod process or the database container and read its log.
  3. The server only listens on localhost. By default mongod accepts 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.
  4. IPv6 versus IPv4. On recent Node.js versions, localhost may resolve to ::1 first, and Node tries both addresses, which is why the message lists ::1 and 127.0.0.1. If the database only listens on IPv4, use 127.0.0.1 in the string or the family: 4 option.

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, use directConnection=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.net

Check 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 ping at 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_URI is empty, with no localhost fallback.
  • Use a single client. One MongoClient per 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/0 makes 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:

  1. 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.
  2. Download the certificate in the dashboard and pass tls: true, tlsCAFile with the CA and tlsCertificateKeyFile with the .pem, because the client also presents the certificate.
  3. Set MONGODB_URI as 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.
  4. Use a single MongoClient in 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

Learn more

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.

Next articleECONNREFUSED: database connection refusedECONNREFUSED means nothing is listening on the database host and port. See the causes (server down, localhost, wrong port, bind address) and how to fix each one.

More in Databases

See all 24 articles