mongoose: { useUnifiedTopology: true } leads to MongoDB connection error: MongoTimeoutError: Server selection timed out after 30000 ms

Do you want to request a feature or report a bug?

A bug.

What is the current behavior?

After updating to Mongoose 5.7.1, the following warning appeared:

(node:41563) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
    at parseFn (/Users/tschaffter/dev/PHCCollaborationPortal/node_modules/mongoose/node_modules/mongodb/lib/operations/connect.js:312:5)
    at parseConnectionString (/Users/tschaffter/dev/PHCCollaborationPortal/node_modules/mongoose/node_modules/mongodb/lib/core/uri_parser.js:628:3)
    at connect (/Users/tschaffter/dev/PHCCollaborationPortal/node_modules/mongoose/node_modules/mongodb/lib/operations/connect.js:266:3)
    at ConnectOperation.execute (/Users/tschaffter/dev/PHCCollaborationPortal/node_modules/mongoose/node_modules/mongodb/lib/operations/connect.js:191:5)
    at executeOperation (/Users/tschaffter/dev/PHCCollaborationPortal/node_modules/mongoose/node_modules/mongodb/lib/operations/execute_operation.js:83:26)
    at MongoClient.connect (/Users/tschaffter/dev/PHCCollaborationPortal/node_modules/mongoose/node_modules/mongodb/lib/mongo_client.js:216:10)
    at Promise (/Users/tschaffter/dev/PHCCollaborationPortal/node_modules/mongoose/lib/connection.js:632:12)
    at Promise._execute (/Users/tschaffter/dev/PHCCollaborationPortal/node_modules/bluebird/js/release/debuggability.js:313:9)
    at Promise._resolveFromExecutor (/Users/tschaffter/dev/PHCCollaborationPortal/node_modules/bluebird/js/release/promise.js:488:18)
    at new Promise (/Users/tschaffter/dev/PHCCollaborationPortal/node_modules/bluebird/js/release/promise.js:79:10)
    at NativeConnection.Connection.openUri (/Users/tschaffter/dev/PHCCollaborationPortal/node_modules/mongoose/lib/connection.js:629:19)
    at Mongoose.connect (/Users/tschaffter/dev/PHCCollaborationPortal/node_modules/mongoose/lib/index.js:327:15)
    at Object.connect (/Users/tschaffter/dev/PHCCollaborationPortal/server/app.js:17:44)
    at Module._compile (internal/modules/cjs/loader.js:778:30)
    at Module._compile (/Users/tschaffter/dev/PHCCollaborationPortal/node_modules/pirates/lib/index.js:99:24)
    at Module._extensions..js (internal/modules/cjs/loader.js:789:10)
    at Object.newLoader [as .js] (/Users/tschaffter/dev/PHCCollaborationPortal/node_modules/pirates/lib/index.js:104:7)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Module.require (internal/modules/cjs/loader.js:692:17)
    at require (internal/modules/cjs/helpers.js:25:18)
    at Object.<anonymous> (/Users/tschaffter/dev/PHCCollaborationPortal/server/index.js:12:28)
    at Module._compile (internal/modules/cjs/loader.js:778:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)

I added useUnifiedTopology: true to my mongoose config object as suggested by the message, even though I’m not using MongoDB replica set or sharded cluster. Here is how I configure and connect using mongoose:

        options: {
            // https://mongoosejs.com/docs/deprecations.html
            useNewUrlParser: true,
            useFindAndModify: false,
            useCreateIndex: true,
            useUnifiedTopology: true,
            reconnectTries: 30,
            reconnectInterval: 500, // in ms
        }
    },

and here is where I used this mongo.options object:

// Connect to MongoDB
const mongooseConnectionPromise = mongoose.connect(config.mongo.uri, config.mongo.options);
mongoose.connection.on('error', err => {
    console.error(`MongoDB connection error: ${err}`);
    process.exit(-1); // eslint-disable-line no-process-exit
});

The warning is gone but the issue is that mongoose is now no longer able to connect:

MongoDB connection error: MongoTimeoutError: Server selection timed out after 30000 ms
[nodemon] app crashed - waiting for file changes before starting...

Here is how I run MongoDB using docker during development:

docker run -p ${MONGO_PORT}:${MONGO_PORT} --name mongo -d mongo

If the current behavior is a bug, please provide the steps to reproduce.

See above

What is the expected behavior?

Mongoose should remove the deprecation warning and run fine when using useUnifiedTopology: true as mongoose suggests.

What are the versions of Node.js, Mongoose and MongoDB you are using? Note that “latest” is not a version.

Node: v10.16.2 Mongoose: 5.7.1 (latest) MongoDB: db version v4.2.0

Related issues:

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 17
  • Comments: 78

Commits related to this issue

Most upvoted comments

Hi! My name is Matt and I’m on the drivers team at MongoDB. We’re very sorry for the outages y’all have been facing, and I wanted to give a little update on the issue:

We’re in the process of trying to phase out our legacy topology types which has turned out to be a very surgical process. Phasing out these types will help greatly reduce the maintenance burden of the driver, and our hope is that means a more stable and efficient driver for our users. In particular, while introducing the “Unified Topology” we did not also introduce the rewrite of the connection pool in an effort to reduce the potential for error. It turns out the connection pool was more tightly coupled to the topology types than we anticipated and as a result we experienced some regressions, particularly around server monitoring.

This morning I pushed a v3.3.4-rc0 of the driver which should address the issues you have been facing. We would be extremely grateful if you could try this version out and report back with your experience. I have left comments on each of the existing tickets related to this issue on NODE-2267, but please feel free to open additional issues there if you experience them.

This is an issue with replica set MongoDB servers and a solution is being worked on here by MongoDB engineers

https://jira.mongodb.org/browse/NODE-2267

@vkarpov15 can probably close this issue because it has nothing to do with Mongoose.

If you’re using MongoDB Atlas, you should whitelist your ip address.

Go to Network Access, edit the current ip address and click on Allow Access from Anywhere.

I’m fairly convinced this is not an issue with mongoose, but with Mongo itself.

@vkarpov15, please see my comment, I outlined my environment there. I’m using mongoose directly.

using mongoose and mongoDB atlas, make sure options are like that: mongoose.connect(DATABASE_URL, { useNewUrlParser: true, useUnifiedTopology: true })

After this, if timeout comes up, u need to whitelist your ip address from mongoDB by going to network access in mongoDB

@mbroadst I didn’t mean to suggest that the MongoNetworkError was new in my last comment, so apologies if that is how it read. It’s the `MongoTimeoutError that is new. To hopefully be clearer, this has been my process:

  1. app has config with useUnifiedTopology: true - everything working as expected
  2. app starts randomly crashing and presents with a MongoTimeoutError matching the title of this issue, as well as the first few lines of a stack trace presented above
  3. a Google / SO search eventually brings me here
  4. I use useUnifiedTopology: false workaround suggested
  5. the MongoTimeoutError error disappears along with the crashing of the app. however, it is replaced by the deprecation warning initially. then, later, by a additional MongoNetworkError not seen in the application before setting useUnifiedTopology: false

Perhaps, as you suggest, this is correlation rather than causation. Just seemed like a smoking gun to me. At least the app is not crashing now. I’m just worried about leaving an option that is deprecated.

The same problem for more than 1 month and it’s not solved yet -_-

I have successfully reproduced the condition that causes “MongoTimeoutError: Server selection timed out after 30000” using docker-compose. https://github.com/anzairyo0127/mongodb-connection-bug

First start this application

$ docker-compose up -d
$ docker-compose exec a mongo /tmp/conf/init.js
$ docker-compose exec node sh
$ npm i && npm run build
$ npm run start
> 0times
> waiting ....
> {_id: 5db27454b77b210040f2f84e, id: 1, text: 'hogehoge'}
> 1times
> waiting ....
> {_id: 5db27454b77b210040f2f84e, id: 1, text: 'hogehoge'}
> xtimes
> waiting ....
> {_id: 5db27454b77b210040f2f84e, id: 1, text: 'hogehoge'}
> ......

and then, open another terminal and execute the following command, 3 seconds after “waiting …” is displayed.

$ docker-compose restart a b c
> xtimes
> waiting ....
> (node: 4360) UnhandledPromiseRejectionWarning: MongoTimeoutError: Server selection timed out after 30000 ms
> at Timeout.setTimeout [as _onTimeout] (/var/work/node_modules/mongodb/lib/core/sdam/topology.js:878:9)
> at ontimeout (timers.js: 436: 11)
> at tryOnTimeout (timers.js: 300: 5)
> at listOnTimeout (timers.js: 263: 5)
> at Timer.processTimers (timers.js: 223: 10)
> (node: 4360) UnhandledPromiseRejectionWarning: Unhandled promise rejection.This error originated either by throwing inside of an> async function without a catch block, or by rejecting a promise which was not handled with .catch (). (rejection id: 1)
> (node: 4360) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that
> are not handled will terminate the Node.js process with a non-zero exit code.

This has nothing to do with access. I have 0/0/0/0 access and this occurs every time server restarts on atlas. You can repro by making a multi node cluster (m10+) and setting the scheduled maintenance time. Then run a long running service and it should produce the error when it restarts.

On Wed., Oct. 23, 2019, 7:42 a.m. Mohammad Mazedul Islam, < notifications@github.com> wrote:

I am only facing this issue while using Atlas. I have tried adding 0.0.0.0/0 IP in whitelist but it also did not work.

I am using:

  • mongoose: 5.7.6
  • node: v10.16.3
  • Atlas free tier

Could not reproduce in local mongodb server. There, every query just works successfully.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/Automattic/mongoose/issues/8180?email_source=notifications&email_token=AAUHUCYYQIQ5U42IBYT7CQTQQA2B7A5CNFSM4IYQ3ZB2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOECBDC4I#issuecomment-545403249, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAUHUCY5SNFGGCPTGW6GH5DQQA2B7ANCNFSM4IYQ3ZBQ .

@vkarpov15 I think you have to pause/resume the cluster to trigger a restart. It’s only possible on M10+ sizes. I also wonder if this might be an Atlas issue instead. I haven’t been able to test the updated MongoDB driver yet, but I’ll report back over here once I do.

We are having this issue as well and we do not use mongoose. It appears to be a problem with the MongoDB driver for Node.js itself. The issue has also been reported over here https://jira.mongodb.org/browse/NODE-2249 Version 3.3.3 of the driver which was published today should add more details to the MongoTimeoutError. It is also recommended to update the driver due to a bugfix.

This error is the result of the driver being unable to connect to a server satisfying the read preference of a given operation (or initial connect). This could be for a number of reasons, including your connection string being invalid or nodes in your cluster being down. If you update to the latest v3.3.3 of the driver we include a new reason field with the MongoTimeoutError which will help us further investigate your issue. Additionally, this version includes a bug fix which would result in a timeout error on initial connect if any member of a replicaset was not available. Please update your driver, and let us know if you continue to experience this issue.

Quoted from https://jira.mongodb.org/browse/NODE-2249?focusedCommentId=2485028&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-2485028

@mtn2bay that doesn’t make any sense you basically used the callback function instead of the promise, the result is still one and the same, the only difference is that in the callback function you get both the connection and the error in the callback function which you’re not logging instead of relying on .then and .catch, so your function is logging connected to db and starting the app either way even if there’s an error. try this instead

mongoose.connect(DATABASE_URL, { 
    useNewUrlParser: true, 
    useUnifiedTopology: true,
}, (err, connection) => {
if(err) {
console.error(err)
return
}    
console.log('Connected to DB');
    app.listen({ port: PORT }, () => {
        console.log(`Server running at http://localhost:${PORT}`);
    })

update - doesn’t work

I was able to solve this issue by changing the structure of my code, specifically the callback as follows:

mongoose.connect(DATABASE_URL, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
}).then(() => {
    console.log('Connected to DB');
    app.listen({ port: PORT }, () => {
        console.log(`Server running at http://localhost:${PORT}`)
    });
}).catch(err => console.log(err));
mongoose.connect(DATABASE_URL, { 
    useNewUrlParser: true, 
    useUnifiedTopology: true,
}, () => {
    console.log('Connected to DB');
    app.listen({ port: PORT }, () => {
        console.log(`Server running at http://localhost:${PORT}`);
    });
}).catch(err => console.log(err));

For people who are having this issue , if you are using Mongo Atlas Cloud Instance , Please see if you are having your IP address specified correctly in the Network Access tab.

I had the issue and it seems that since my ISP gives out New IPs everytime (DHCP) i reconnect to the network , Mongo Atlas was only white listing the previously specified IP address. Hope this helps someone.

@mbroadst done! Thanks NODE-2313

@rvanmil I can reproduce it in ver3.3.3.

It seems like this error occurs when the mongoDB is in replication configuration and one of the instance (probably the primary instance) receives a command just before it goes down or right after its startup. I think the reason why this happens frequently on MongoDB Atlas is that MongoDB Atlas regularly sends queries to the cluster for monitoring.

I also used to have that issue. But now after putting both 0.0.0.0/0 and my IP address to whitelist from atlas solves the problem.

I am also getting both errors (Server selection timed out after 30000 ms and MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11) when using useUnifiedTopology so this is happening to everyone that uses this option I guess.

For people who are having this issue , if you are using Mongo Atlas Cloud Instance , Please see if you are having your IP address specified correctly in the Network Access tab.

I had the issue and it seems that since my ISP gives out New IPs everytime (DHCP) i reconnect to the network , Mongo Atlas was only white listing the previously specified IP address. Hope this helps someone.

solved my issue UnhandledPromiseRejectionWarning: MongoTimeoutError: Server selection timed out after 30000 ms at Timeout.setTimeout (C:\Users\Umer MIB\Desktop\Chatbots2\mongobot\node_modules\mongodb\lib\core\sdam\topology.js:878:9) at ontimeout (timers.js:436:11) at tryOnTimeout (timers.js:300:5) at listOnTimeout (timers.js:263:5) at Timer.processTimers (timers.js:223:10) (node:4304) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1) (node:4304) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code

when your current ip address changes for some reason the connection fails, you should edit it in Network access ip whitelist and use the current ip

Also happening here. Our production server responds with the bellow message. I gues I will comment useUnifiedTopology for now

MongoDB Connection Options

var options = {
    useCreateIndex: true,
    useNewUrlParser: true,
    useFindAndModify: false,
    useUnifiedTopology: true,
    promiseLibrary: global.Promise
};

Server Log

MongoTimeoutError: Server selection timed out after 30000 ms 
Oct 16 12:56:31 app/web.1:     at Timeout.setTimeout (/app/node_modules/mongodb/lib/core/sdam/topology.js:850:16) 
Oct 16 12:56:31 app/web.1:     at Shim.applySegment (/app/node_modules/newrelic/lib/shim/shim.js:1424:20) 
Oct 16 12:56:31 app/web.1:     at Timeout.wrappedCallback [as _onTimeout] (/app/node_modules/newrelic/lib/shim/shim.js:1281:21) 
Oct 16 12:56:31 app/web.1:     at ontimeout (timers.js:436:11) 
Oct 16 12:56:31 app/web.1:     at tryOnTimeout (timers.js:300:5) 
Oct 16 12:56:31 app/web.1:     at listOnTimeout (timers.js:263:5) 
Oct 16 12:56:31 app/web.1:     at Timer.processTimers (timers.js:223:10) 

Also happening here. Our production server responds with the bellow message. I gues I will comment useUnifiedTopology for now

MongoDB Connection Options

var options = {
    useCreateIndex: true,
    useNewUrlParser: true,
    useFindAndModify: false,
    useUnifiedTopology: true,
    promiseLibrary: global.Promise
};

Server Log

MongoTimeoutError: Server selection timed out after 30000 ms 
Oct 16 12:56:31 app/web.1:     at Timeout.setTimeout (/app/node_modules/mongodb/lib/core/sdam/topology.js:850:16) 
Oct 16 12:56:31 app/web.1:     at Shim.applySegment (/app/node_modules/newrelic/lib/shim/shim.js:1424:20) 
Oct 16 12:56:31 app/web.1:     at Timeout.wrappedCallback [as _onTimeout] (/app/node_modules/newrelic/lib/shim/shim.js:1281:21) 
Oct 16 12:56:31 app/web.1:     at ontimeout (timers.js:436:11) 
Oct 16 12:56:31 app/web.1:     at tryOnTimeout (timers.js:300:5) 
Oct 16 12:56:31 app/web.1:     at listOnTimeout (timers.js:263:5) 
Oct 16 12:56:31 app/web.1:     at Timer.processTimers (timers.js:223:10) 

I am using mongo db atlas and we are facing the same problem.

dub-tools-jobs: orders - error MongoTimeoutError: Server selection timed out after 30000 ms 
Oct 29 13:16:30 app/worker.1:      at Timeout.setTimeout [as _onTimeout] (/app/node_modules/mongoose/node_modules/mongodb/lib/core/sdam/topology.js:850:16) 
Oct 29 13:16:30 app/worker.1:     at ontimeout (timers.js:436:11) 
Oct 29 13:16:30 app/worker.1:     at tryOnTimeout (timers.js:300:5) 
Oct 29 13:16:30 app/worker.1:     at listOnTimeout (timers.js:263:5) 
Oct 29 13:16:30 app/worker.1:     at Timer.processTimers (timers.js:223:10) +2m

this all happened with commenting useUnifiedTopology as one recommendation suggested

// mongodb connections
var options = {
    useCreateIndex: true,
    useNewUrlParser: true,
    useFindAndModify: false,
    // useUnifiedTopology: true,      
    promiseLibrary: global.Promise
};

I have the same problem using normal MongoDB.

I am only facing this issue while using Atlas. I have tried adding 0.0.0.0/0 IP in whitelist but it also did not work.

I am using:

  • mongoose: 5.7.6
  • node: v10.16.3
  • Atlas free tier

Could not reproduce in local mongodb server. There, every query just works successfully.

So I’m still unable to repro this locally with a replica set. The below script continues to execute queries successfully even with replica set failover or killing the primary. Don’t get any server selection timeout errors:

'use strict';

const mongoose = require('mongoose');

run().catch(err => console.log(err));

async function run() {
  mongoose.set('useUnifiedTopology', true);
  mongoose.set('useNewUrlParser', true);

  await mongoose.connect('mongodb://localhost:27017,localhost:27018,localhost:27019/test?replicaSet=rs');

  const Model = mongoose.model('Test', new mongoose.Schema({ name: String }));
  

  while (true) {
    console.log(new Date(), 'Query...');
    await Model.findOne();
    await new Promise(resolve => setTimeout(resolve, 5000));
  }
} 

My best guess is @rvanmil 's explanation is correct. Try upgrading to mongoose@5.7.6 (which I’ll ship in a couple hours) and see if this issue persists.

Can confirm that commenting useUnifiedTopology out solves the problem in my build. Also happening in a (apparently) random fashion.

I started to encounter another problem now MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 topologyDescriptionChanged listeners added.

When I searched for this warning I came across this mongoDB document https://jira.mongodb.org/browse/NODE-2123

It states both the errors "Server selection timed out " as well as “MaxListenersExceededWarning” and both the errors are due to the unified topology change. I guess this was a breaking change which was never mentioned.

Since I am encountering this error on my live server I have no choice but to set { useUnifiedTopology: false }. I hope someone from the community can focus on this issue and resolve it or provide some suggestions to resolve it.

Hey, just poking in here to report that I had the same issue.

I myself am not using Docker or any vm. Also to note is that this doesn’t seem to happen all the time, however today I was unable to retreive any of my data due to timeouts (30k), and the issue was immediately resolved when removing the useUnifiedTopology flag.

I’m connecting to an Atlas cluster.

Mongoose is 5.7.1 MongoDb is 3.3.2 Node is 12.9.1

Connecting like this:

mongoose.createConnection(uri,
	{
		useCreateIndex: true,
		useNewUrlParser: true,
		useUnifiedTopology: true, // commented out currently
		dbName: db_name
	});

The model is created like this:

import mongoose from 'mongoose';
import * as db_conns from '../db-connections'; // this is an object of connections generated via createConnection

// ... schema definition, for a model called 'article' from a collection called 'article'

// `site_content` is the name of a connection
export default db_conns.connections.site_content.model(`article`, schema, `article`);

Then it’s fetched like this:

// ...
await query.model.find(query_expr).limit(30); // query_expr can change, however even an empty expression ({}) will cause the same issue
// ...

The find call hangs and issues the timeout error.