Automattic / mongoose

MongoDB object modeling designed to work in an asynchronous environment.
https://mongoosejs.com
MIT License
26.88k stars 3.83k forks source link

Mongoose 4.6.2 produces error "MongoError: no primary found in replicaset" while 4.4.19 works just fine #4596

Closed adeelzaman closed 5 years ago

adeelzaman commented 7 years ago

Simple connection to a MongoDB replica set. Works great in Mongoose 4.4.19 but not in 4.6.2

mongoURI = "mongodb://IP:27017,IP:27017/" + dbName + "?replicaSet=my_replica_set";

Using 4.6.2, I have tried the following:

If connection string only uses one database, it works fine. I am really curious as to why this error occurs. Any thoughts?

Full Error:

/Users/adeel/dev/navi/euler/node_modules/mongodb/lib/replset.js:360 process.nextTick(function() { throw err; }) ^ MongoError: no primary found in replicaset at /Users/adeel/dev/navi/euler/node_modules/mongodb-core/lib/topologies/replset.js:631:32 at . (/Users/adeel/dev/navi/euler/node_modules/mongodb-core/lib/topologies/replset.js:421:24) at g (events.js:286:16) at emitOne (events.js:96:13) at emit (events.js:188:7) at . (/Users/adeel/dev/navi/euler/node_modules/mongodb-core/lib/topologies/server.js:313:21) at emitOne (events.js:96:13) at emit (events.js:188:7) at . (/Users/adeel/dev/navi/euler/node_modules/mongodb-core/lib/connection/pool.js:260:12) at g (events.js:286:16) at emitTwo (events.js:106:13) at emit (events.js:191:7) at Socket. (/Users/adeel/dev/navi/euler/node_modules/mongodb-core/lib/connection/connection.js:162:49) at Socket.g (events.js:286:16) at emitOne (events.js:96:13) at Socket.emit (events.js:188:7)

Trenrod commented 7 years ago

@wayofthefuture "I read somewhere that the primary will send the addresses of the other 2 secondaries." Do you have a source. Bcos this didnt work for me eigther nor any workaround suggested here. Im stucked in the same situation like op. :/

wayofthefuture commented 7 years ago

Sometimes I wonder if it would just be better to use straight up Mongo API? Is it really more beneficial to get stuck with problems like these because we wanted something that was easier to work with? Sometimes it feels like an unnecessary abstraction layer.

vkarpov15 commented 7 years ago

@wayofthefuture agreed, we're planning on that but haven't done so yet.

rushabhnagda11 commented 7 years ago

Can confirm this issue on 4.9.0.

Running mongo in Kubernetes with 3 nodes in a Replication Controller. My node server using mongooose is connecting to my mongo cluster in a different namespace.

If my nodeserver and mongo cluster is in the same namespace (no dns resolution required) it works.

asabhaney commented 7 years ago

Was able to figure out the issue, thanks to more specific error messages with the latest driver upgrades (now using mongoose 4.9.2). The issue was that mongoose was trying to connect to each host specified in the mongo replica set configuration, rather than using the hosts I specified in my mongoose connection string. And since my node server and mongo cluster are running in separate namespaces, my node server was unable resolve the DNS for these hosts.

wayofthefuture commented 7 years ago

Can you please explain what you did to solve the problem? My Mongo Cluster is running in a separate namespace as well. Thanks.

asabhaney commented 7 years ago

@wayofthefuture I'm not sure if I did it in the best way, but I just edited the /etc/hosts file on my host where the node server is running.

So for example, let's say the hosts specified in your replica set configuration are db1.example.com and db2.example.com. But then for some reason (like firewall configuration), the host where your node server is running can't resolve these two hostnames. So in your mongoose connection configuration string you are using different hostnames or IP addresses (for example 10.0.0.1 and 10.0.0.2). If this is the case, then you could edit the /etc/hosts file (on the same host as the node server is running) to include the lines:

10.0.0.1 db1.example.com
10.0.0.2 db2.example.com

At least that's what my issue was - I'm not sure that this applies to this will apply to your situation as well. Bizarre that a different version of the mongo driver could cause an issue like this. Anyway, hope that helps.

JonathanYates commented 7 years ago

Confirm same error: Mongoose default connection error: MongoError: no primary found in replicaset.

Using mongoose 4.9.3. and docker compose. Not sure if docker is anything to do with it, but reverting to 4.5.10 resolved the issue.

Please can someone take a serious look into this issue as it was raised 7 months ago with no solution other than to revert to 4.5.10.

wayofthefuture commented 7 years ago

@asabhaney You are right... now it is trying to connect to the internal IP addresses of each cluster node. This seems like a bug still to me though, because if I specify a domain name with a static IP, it should use that static IP and not try to use the internal IP in another subnet. The /etc/hosts fix is a solution but seems like a temporary fix for a bigger problem, right? Thanks.

ekryski commented 7 years ago

I'm wondering if this an underlying issue with the native mongodb driver? I'm also seeing issues connecting to replica sets through Heroku. It's just bombing not being able to find a primary.

wparsons-360insights commented 7 years ago

I haven't looked, but unless the native mongodb driver being used between the known working and known not working versions of mongoose was changed, it can't be just the native driver at fault.

liquidscorpio commented 7 years ago

+1 Reverting to v4.5.10 works.

Node versions tested against

v7.7.3 v7.10.0 lts/boron

Mongoose versions tested and failed with "No primary found"

5.6.2 5.7.0 5.8.5

Mongo versions

3.2 2.6

Reproducibility

Consistent

Any leads where to even start looking to get underneath this bug?

liquidscorpio commented 7 years ago

Is this issue related to https://github.com/Automattic/mongoose/issues/4517? While that issue is marked closed I am not sure if the issue was resolved. Newer versions still have this problem.

dtzar commented 7 years ago

I've verified this error exists against Azure CosmosDB using the 4.9.10 version of the driver. It also exists against the 4.5.10 driver with CosmosDB too unless you specify &readPreference=secondary at the end of the connection string - then it works fine.

vkarpov15 commented 7 years ago

@dtzar fair warning, supporting CosmosDB/DocumentDB is currently a non-goal for mongoose. If you choose to use mongoose with those dbs you're on your own.

ronenteva commented 7 years ago

Issue still exists on Mongoose 4.10.2

wayofthefuture commented 7 years ago

I connected using the mongo native driver and the issue still occurred. It's not mongoose it's the config file settings IP addresses on each one of the computers in the cluster. You have to change the IP address to the public external IP address and not the internal IP. When I used Mongo Atlas official service it was already setup ready to go no modification required as far as IPs are concerned.

dtzar commented 7 years ago

@wayofthefuture are you referring to CosmosDB? I also realized connecting to CosmosDB worked via Mongoose 4.5.10 if you drop the &replicaset=globaldb at the end.

cula commented 7 years ago

Issue still exists on Mongoose 4.10.2 Any update?

dtzar commented 7 years ago

This issue is no longer present with the latest Mongoose version as far as I can see connecting to CosmosDB using MongoDB API as long as you specify the connection string in the following format:

mongodb://myservername:mypassword@myservername.documents.azure.com:10255/mydbname?ssl=true&replicaSet=globaldb

It's important to call out the fact that the mydbname is not present by default in the Azure portal and must be inserted or else the connection WILL fail with the mentioned issue above. It doesn't matter what value you provide for mydbname, but it must be there.

vunb commented 7 years ago

Try to fix hostname of mongodb server in /etc/hosts, for example:

1.2.3.4 mdb01 mdb01.example.com
1.2.3.5 mdb02 mdb02.example.com
1.2.3.6 mdb03 mdb03.example.com

Hope this help !

aichholzer commented 7 years ago

Using V. 4.11.5 on Heroku. -At first I had the same issues, I fixed it by just adding replicaSet to the connection string:

mongodb://user:pass@mongolayer.com,mongolayer.com/database?replicaSet=database

Note that the value passed as replicaSet is the same as the database name. I have not tried using different names.

I hope this helps.

wethinkagile commented 6 years ago

Solution:

    options.replset = {
      socketOptions: {
        connectTimeoutMS: 60000, 
        keepAlive: 120
      }
    };
ChrisBarriere commented 6 years ago

setting /etc/hosts works for me

aleczratiu commented 6 years ago

I think you can open compass and cluster connection in web tab and choose connect to compass and compass app automatically detect the connection :)

sravzpublic commented 6 years ago

I get the same error in Node 8. Node 6 works fine. Any ideas?

Error: Cannot determine state of server at canCheckoutReader (PATH_TO/node_modules/connect-mongo/node_modules/mongodb/lib/mongodb/connection/server.js:779:12) at Server.checkoutReader (PATH_TO/node_modules/connect-mongo/node_modules/mongodb/lib/mongodb/connection/server.js:793:16) at Cursor.nextObject (PATH_TO/node_modules/connect-mongo/node_modules/mongodb/lib/mongodb/cursor.js:748:48) at Collection.findOne (PATH_TO/node_modules/connect-mongo/node_modules/mongodb/lib/mongodb/collection/query.js:162:10) at PATH_TO/node_modules/connect-mongo/lib/connect-mongo.js:223:18 at MongoStore._get_collection (PATH_TO/node_modules/connect-mongo/lib/connect-mongo.js:156:21) at MongoStore.get (PATH_TO/node_modules/connect-mongo/lib/connect-mongo.js:222:10) at session (PATH_TO/node_modules/express-session/index.js:367:11) at Layer.handle [as handle_request] (PATH_TO/node_modules/express/lib/router/layer.js:82:5) at trim_prefix (PATH_TO/node_modules/express/lib/router/index.js:269:13) at PATH_TO/node_modules/express/lib/router/index.js:236:9 at Function.proto.process_params (PATH_TO/node_modules/express/lib/router/index.js:311:12) at PATH_TO/node_modules/express/lib/router/index.js:227:12 at Function.match_layer (PATH_TO/node_modules/express/lib/router/index.js:294:3) at next (PATH_TO/node_modules/express/lib/router/index.js:188:10) at cookieParser (PATH_TO/node_modules/cookie-parser/index.js:48:5)

Node Version v6.13.0 -> WORKS v8.10.0 -> Throws that error. Does mongoose support Node8?

npm list | grep mongoose ├─┬ mongoose@5.0.11 │ ├── mongoose-legacy-pluralize@1.0.2

npm list | grep mongodb │ └── mongodb@1.4.40 extraneous ├─┬ mongodb@3.0.3 invalid │ └── mongodb-core@3.0.3 extraneous │ ├─┬ mongodb@3.0.4 │ │ └─┬ mongodb-core@3.0.4

Mongoose connects to Mongos on port 26000. I can connect to Mongodb with Robomongo

vkarpov15 commented 6 years ago

@sravzpublic please look closely at your stack trace, it shows that the error is in connect-mongo and has nothing to do with mongoose. FWIW, mongoose does support node 8.

prologic commented 5 years ago

We experience this too on Mongoose 5.2.12 (much newer than reported here) on NodeJS 6.x -- Haven't had too much time to dig into it yet :/

patientplatypus commented 5 years ago

I am getting this issue on "mongoose": "^5.4.19", and have provided examples on an open stackoverflow here: https://stackoverflow.com/questions/55637808/mongoerror-no-mongos-proxy-available-when-connecting-to-replica-set. It's concerning that this seems to be an open issue for so long and through a version upgrade even. Hmm....

PS: If anyone figures this out can you please provide a full working example? There's recommendations to solutions in this thread where I don't even know what version they are using...

fd98279 commented 5 years ago

I faced this issue in node 8 I upgrade to node 10 and have these packages and restructured my mongodb connection logic to below. It worked.

cat package.json | grep mongo "connect-mongo": "^2.0.1", "mongodb": ">=3.0.4", "mongoose": ">=5.0.11",

node -v v10.4.1

db.version() 3.4.15

config.db = mongodb://user:pass@host:26000/dbname?ssl=true

// Get Mongoose to use the global promise library
mongoose.Promise = global.Promise;
var db = mongoose.connect(config.db, {
    auto_reconnect: true,
    socketTimeoutMS: 0,
    connectTimeoutMS: 0
  },
  function (err) {
    if (err) {
      console.error(chalk.red('Could not connect to MongoDB!' + err));
      console.log(chalk.red(err));
    }
  });

// When successfully connected
mongoose.connection.on('connected', function () {
 };

// If the connection throws an error
mongoose.connection.on('error', function (err) {
  console.log('Mongoose default connection error: ' + err);
});

// When the connection is disconnected
mongoose.connection.on('disconnected', function () {
  console.log('Mongoose default connection disconnected');
});

process.on('SIGINT', function () {
  mongoose.connection.close(function () {
    console.log('Mongoose default connection disconnected through app termination');
    process.exit(0);
  });
});
djguruwap commented 5 years ago

i think the problem is on host: (cluster0-shard-00-00-vmyny.mongodb.net) use the primary one.

vkarpov15 commented 5 years ago

I'm going to close this, it looks like the issue is with connect-mongo, not mongoose.