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)

ashishtilara commented 7 years ago

+1

vkarpov15 commented 7 years ago

Can you connect with the mongo shell?

adeelzaman commented 7 years ago

I can connect with mongo shell. The DB is working fine. We are in production and many microservices are connected to the DB using the replica set string.

However, for new projects, connecting using the replica set string doesn't seem to work. And we have to use just the IP address of the master node. I first thought this was a version issue (4.6.2 vs 4.4.19).

However, recently I wasn't able to connect using the replica string on 4.6.2 either on the new project. As a temporary solution, I decided to just use the IP address for the master node (connection string with just one IP address).

zoellner commented 7 years ago

I am seeing similar issues. Can't really add more clarification or provide a good code example. But my suspicion is that this has to do with an incompatibility of one of the dependencies.
The first time I have observed this issue was when I updated other packages (but not mongoose which was at 4.5.8 at the time)

adeelzaman commented 7 years ago

@zoellner If you are able to post a shortlist of some of the packages you updated right before this issue started for you, I can check it against my own list and we can try to pinpoint where the incompatibility lies.

Considering this issue only occurs on new projects for me, it is very possible that it is due to Mongoose incompatibility with a newer version of a different npm package.

zoellner commented 7 years ago

@adeelzaman I've created a diff of my project's npm-shrinkwrap.json for the commit that started to cause the issues. It's a bit long, so I've put it here: https://gist.github.com/zoellner/eddd3d40291e150919bb025f452f9054

zoellner commented 7 years ago

@adeelzaman I've updated the gist above just now with one that I confirmed is causing the issue

dan-perron commented 7 years ago

@zoellner I can't tell from that gist which one is the cause, can you enlighten us?

adeelzaman commented 7 years ago

I found out that for us the issue does not occur for Mongoose 4.5.8. Temporarily we have locked our repos into 4.5.8 of Mongoose to solve the problem.

Also I should mention that when attempting to isolate the problem, I created a brand new project with only one node module (mongoose) and attempted to connect to the replica set using 4.6.0 and got the same error.

So maybe it isn't an incompatibility error but an error with 4.6.0? I couldn't pinpoint any further as per what was causing the error. I plan to look into it more when I get some free time.

zakpatterson commented 7 years ago

I just ran into what I'm pretty sure is the same issue on 4.6.2 and 4.6.4, I get this output for my replicaset connection, same config uri setup as above

Error: Uncaught, unspecified "error" event. ([object Object])
    at NativeConnection.emit (events.js:163:17)
    at /home/projects/xxx/xxx/node_modules/mongoose/lib/connection.js:466:17
    at NativeConnection.Connection.error (/home/projects/xxx/xxx/node_modules/mongoose/lib/connection.js:489:12)
    at /home/projects/xxx/xxx/node_modules/mongoose/lib/connection.js:520:15
    at /home/projects/xxx/xxx/node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js:216:21
    at /home/projects/xxx/xxx/node_modules/mongodb/lib/db.js:229:14
    at .<anonymous> (/home/projects/xxx/xxx/node_modules/mongodb/lib/replset.js:357:9)
    at g (events.js:286:16)
    at emitOne (events.js:96:13)
    at emit (events.js:188:7)
    at Timeout.<anonymous> (/home/projects/xxx/xxx/node_modules/mongodb-core/lib/topologies/replset.js:507:14)
    at tryOnTimeout (timers.js:232:11)
    at Timer.listOnTimeout (timers.js:202:5)
vkarpov15 commented 7 years ago

Hmm strange. This is almost certainly an issue with the underlying mongodb driver, because mongoose doesn't do anything with replica sets on its own. There were some issues with replica sets that were fixed in mongodb driver 2.2.11, will upgrade for mongoose 4.6.5 and see if that fixes it.

mo4islona commented 7 years ago

+1

vkarpov15 commented 7 years ago

@mo4islona still happening in 4.6.5?

alexanderMykhailenko commented 7 years ago

+1 the same problem (in 4.6.5 also). Latest working version 4.5.9 after this version 4.6.0 and more i receive error "no primary found in replicaset"

mo4islona commented 7 years ago

@vkarpov15 Yes 4.6.5 doesn't work. Didn't try 4.5.9 but 4.4.19 works.

dottodot commented 7 years ago

same problem here using a uri such as

mongodb://user:password@server1,server2,server3/database?replicaSet=repname

works on 4.5.9 but latest version gives errors

stampsrule commented 7 years ago

today I did an install on ubuntu 14 with mongoose 4.5.9 and got the same error /node_modules/mongodb/lib/mongo_client.js:225 throw err ^ MongoError: no primary found in replicaset at /node_modules/mongodb-core/lib/topologies/replset.js:628:32 at Server.<anonymous> (test/node_modules/mongodb-core/lib/topologies/replset.js:420:24)

the same code was working no problem on mac OSX

my uri is same as dottodot

vkarpov15 commented 7 years ago

Weird. Can you confirm whether you can connect using the mongodb shell using that URI from the same machine?

stampsrule commented 7 years ago

@vkarpov15 I can connect using the mongodb shell and I can connect using the standard URI way

vkarpov15 commented 7 years ago

@stampsrule what's the standard URI way?

stampsrule commented 7 years ago

@vkarpov15

mongodb://user:password@server:port/database

vkarpov15 commented 7 years ago

Ok so what's the connection code that's failing?

asabhaney commented 7 years ago

I'm having a similar issue, I am unable to connect in mongoose >= 4.6.0. Reverting to 4.5.10 works. My connection string looks like:

mongodb://username:password@ip1:port1,ip2:port2/database?authSource=blah&replicaSet=rs0&ssl=true

I'm using the following connection options:

{
   replSet: {
      sslValidate: false,
      sslCert: fs.readFileSync(`...`),
      sslKey: fs.readFileSync(`...`),
      sslCA: fs.readFileSync(`...`)
   }
}

If I define an error handler for the connection, like so:

 mongoose.connection.on('error', (err) => {
    console.log(err instanceof Error, err)
})

then interestingly err instanceof Error is false, and the output of logging err is:

 ReplSet {
  domain: null,
  _events: 
   { reconnect: [Function],
     timeout: { [Function: g] listener: [Function] },
     error: { [Function: g] listener: [Function] },
     connect: { [Function: g] listener: [Function: connectHandler] } },
  _eventsCount: 4,
  _maxListeners: undefined,
  id: 1,
  s: 
   { options: 
      { disconnectHandler: [Object],
        cursorFactory: [Object],
        reconnect: false,
        emitError: true,
        size: 5,
        rejectUnauthorized: false,
        cert: <Buffer  ... >,
        key: <Buffer  ... >,
        ca: <Buffer  ... >,
        socketOptions: {},
        setName: 'rs0',
        ssl: true,
        clientInfo: [Object] },
     bson: BSON {},
     Cursor: 
      { [Function: Cursor]
        super_: [Object],
        define: [Object],
        INIT: 0,
        OPEN: 1,
        CLOSED: 2,
        GET_MORE: 3 },
     logger: Logger { className: 'ReplSet' },
     seedlist: [ [Object], [Object] ],
     replicaSetState: 
      ReplSetState {
        domain: null,
        _events: [Object],
        _eventsCount: 3,
        _maxListeners: undefined,
        topologyType: 'ReplicaSetNoPrimary',
        setName: 'rs0',
        set: {},
        id: 1,
        logger: [Object],
        index: 0,
        acceptableLatency: 15,
        heartbeatFrequencyMS: 10000,
        primary: null,
        secondaries: [],
        arbiters: [],
        passives: [],
        ghosts: [],
        unknownServers: [],
        maxElectionId: null,
        maxSetVersion: 0,
        replicasetDescription: [Object] },
     connectingServers: [],
     haInterval: 10000,
     minHeartbeatFrequencyMS: 500,
     disconnectHandler: Store { s: [Object], length: [Getter] },
     index: 0,
     connectOptions: { forceServerObjectId: false, w: 1, promiseLibrary: [Object] },
     debug: false,
     clientInfo: 
      { driver: [Object],
        os: [Object],
        platform: 'Node.js v6.7.0, LE, mongodb-core: 2.0.13' } },
  authProviders: 
   { mongocr: MongoCR { bson: BSON {}, authStore: [] },
     x509: X509 { bson: BSON {}, authStore: [] },
     plain: Plain { bson: BSON {}, authStore: [] },
     gssapi: GSSAPI { bson: BSON {}, authStore: [] },
     sspi: SSPI { bson: BSON {}, authStore: [] },
     'scram-sha-1': ScramSHA1 { bson: BSON {}, authStore: [], id: 0 } },
  initialConnectState: { connect: false, fullsetup: false, all: false },
  state: 'destroyed',
  haTimeoutId: 
   Timeout {
     '0': null,
     _called: true,
     _idleTimeout: -1,
     _idlePrev: null,
     _idleNext: null,
     _idleStart: 1969,
     _onTimeout: null,
     _repeat: null },
  authenticating: false,
  ismaster: null }

Some other details:

saguila commented 7 years ago

use mongoose@4.4.12,the last version don't work.i had the same problem(repset).

dustywusty commented 7 years ago

@adeelzaman is your replica set hosted in an environment where you may have more than one address to access each of the replica set members e.g. internal and external?

adeelzaman commented 7 years ago

@dustywusty No, it doesn't. One IP address per replica set member.

wparsons-360insights commented 7 years ago

I have this issue happening with 4.6.0 and newer, 4.5.10 is the last working version for me.

flipflopapp commented 7 years ago

Kindly review if this issue is similar to - https://github.com/Automattic/mongoose/issues/4834

stampsrule commented 7 years ago

I am using the latest version and logged self.s.replicaSetState at the time of the error and found this: topologyType: 'ReplicaSetNoPrimary', setName: 'rs0', set: { 'mongo1:27017': { type: 'Unknown', electionId: null, setName: null, setVersion: null }, 'mongo2:27017': { type: 'PossiblePrimary', setVersion: null, electionId: null, setName: null }, 'mongo3:27017': { type: 'Unknown', electionId: null, setName: null, setVersion: null }, 'database4ca:27017': { type: 'RSSecondary', electionId: undefined, setName: 'rs0', setVersion: 5 }, 'mongoarb:27017': { type: 'Unknown', electionId: null, setName: null, setVersion: null } },

are the null values causing the error?

stampsrule commented 7 years ago

that was 100% the problem, when I put in mongo1.example.com:27017 it would not connect even though the IP worked. when I resolved the URL issue and replaced my mongodb:// URI with URLs all worked.

mengfoobar commented 7 years ago

saw @wparsons-360insights 's comment and tried it out. Confirming that the exact same db connection for replica set works in 4.5.10 but not in 4.7.1

tapankumar commented 7 years ago

Hi,

I am facing the same issue.

mongoose": "^4.7.6"

config: config.mongoose = { uri: "mongodb://Appinv-db:27017,Appinv-db1:27017,Appinv-db2:27017,Appinv-db3:27017/nexgtv_16?replicaSet=rs0", //uri: "mongodb://localhost/nexgtv_16", options: { db: { native_parser: true }, replset: { //auto_reconnect: false, poolSize: 10, socketOptions: { keepAlive: 1000, connectTimeoutMS: 30000 }, reconnectInterval: 2000, //Default is 1000 ms reconnectTries: 60 //Default is 30 }, server: { poolSize: 5, socketOptions: { keepAlive: 1000, connectTimeoutMS: 30000 }, reconnectInterval: 2000, //Default is 1000 ms reconnectTries: 60 //Default is 30 } } }

Connection: mongoose.connect(config.mongoose.uri, config.mongoose.options);

Error: MongoError: connection 3 to Appinv-db3:27017 closed at Function.MongoError.create (/etc/scripts/push-notifications/node_modules/mongodb-core/lib/error.js:29:11) at Socket. (/etc/scripts/push-notifications/node_modules/mongodb-core/lib/connection/connection.js:198:22) at Socket.g (events.js:291:16) at emitOne (events.js:96:13) at Socket.emit (events.js:188:7) at TCP._handle.close [as _onclose] (net.js:498:12) connection error: { MongoError: no primary found in replicaset at /etc/scripts/push-notifications/node_modules/mongodb-core/lib/topologies/replset.js:659:32 at Server. (/etc/scripts/push-notifications/node_modules/mongodb-core/lib/topologies/replset.js:442:24) at Server.g (events.js:291:16) at emitOne (events.js:96:13) at Server.emit (events.js:188:7) at Object.cb (/etc/scripts/push-notifications/node_modules/mongodb-core/lib/topologies/server.js:259:55) at Connection. (/etc/scripts/push-notifications/node_modules/mongodb-core/lib/connection/pool.js:243:32) at Connection.g (events.js:291:16) at emitTwo (events.js:106:13) at Connection.emit (events.js:191:7) at Socket. (/etc/scripts/push-notifications/node_modules/mongodb-core/lib/connection/connection.js:197:12) at Socket.g (events.js:291:16) at emitOne (events.js:96:13) at Socket.emit (events.js:188:7) at TCP._handle.close [as _onclose] (net.js:498:12) name: 'MongoError', message: 'no primary found in replicaset' }

Please suggest any solution

imaksp commented 7 years ago

Having similar issue with mLab on heroku with replica in uri fixed by using 4.5.10 version

dan-perron commented 7 years ago

We are encountering this issue as well, but a recent upgrade from MongoDB 3.0 -> 3.4 seems to allow the most recent version of mongoose to run stably.

(Not sure if it's due to 4.7.8 or 3.4 or a combination of the two)

dazwiafl commented 7 years ago

I've had the same problem. Adding the replicasets members hostnames (like they are on the replset hostsfile) to the webservers hostsfile fixed the issue for me.

rs.conf();
{
    "_id" : "cwreplset0",
    "version" : 348189,
    "protocolVersion" : NumberLong(1),
    "members" : [
        {
            "_id" : 0,
            "host" : "cwmongo1:27017",
            "arbiterOnly" : false,
            "buildIndexes" : true,
            "hidden" : false,
            "priority" : 2,
            "tags" : {

            },
            "slaveDelay" : NumberLong(0),
            "votes" : 1
        },
        {
            "_id" : 1,
            "host" : "cwmongoArbiter:27017",
            "arbiterOnly" : true,
            "buildIndexes" : true,
            "hidden" : false,
            "priority" : 1,
            "tags" : {

            },
            "slaveDelay" : NumberLong(0),
            "votes" : 1
        },
        {
            "_id" : 2,
            "host" : "cwmongo2:27017",
            "arbiterOnly" : false,
            "buildIndexes" : true,
            "hidden" : false,
            "priority" : 1,
            "tags" : {

            },
            "slaveDelay" : NumberLong(0),
            "votes" : 1
        }
    ],
...
cwmongo1 /etc/hosts:
127.0.0.1   cwmongo1
XXX cwmongo2
XXX cwmongoArbiter

cwmongo2 /etc/hosts:
127.0.0.1   cwmongo2
XXX cwmongo1
XXX cwmongoArbiter

cwmongoArbiter /etc/hosts:
127.0.0.1   cwmongoArbiter
XXX cwmongo2
XXX cwmongo1
webservers /etc/hosts:

XXX cwmongo1
XXX cwmongo2
imaksp commented 7 years ago

Surprisingly issue fixed for me with replicaSet param in mLab MONGODB_URI after updating to latest version 4.8.1.

zoellner commented 7 years ago

given @dazwiafl's comment, is it possible that the error occurs when the "host" in the replicaset configuration on the mongodb server doesn't match the server names in the connection string? E.g. when custom (internal) dns names or IP addresses are used? Looking through the previous comments it seems to be the case for everyone who mentioned their hostnames. In that case #4834 would actually be the same issue as suggested by @flipflopapp EDIT: #3634 could be related as well

zoellner commented 7 years ago

Confirming that mongoose 4.8.1 works for us (with mongodb 3.4.2) if and only if we use the full (external) dns names in the connection string.

We previously used an internal dns name (that resolved to a private EC2 IP address within our VPC). This doesn't work when the host names in the rs.conf() is set to the external dns names. I haven't tested all configurations, but my intuition at this point tells me that the mongoose/mongodb version doesn't really matter. This problem should be solved when using the full dns names.

dottodot commented 7 years ago

@zoellner I have a similar setup where I'm connecting to mongo via private network so there is no external access, so how do you get round that? Before I could just connect using the private ip addresses. I've been trying to find an answer but without much luck.

zoellner commented 7 years ago

I made some infrastructure changes to allow "external access" (limited to the servers who need it). Not an ideal solution but will work for a while until there's a better way. I think it's really an issue to raise with the folks at mongodb to better handle this rather common scenario

phutchins commented 7 years ago

@dottodot You should be able to set sslAllowInvalidCertificates and sslAllowInvalidHostnames on the client side, and set the self signed cert up to use localhost or 127.0.0.1 for the FQDN. This is working for me with IP's as the host field in the replicaset and still am accessing the hosts via a hostname that doesn't match the hosts's hostname or FQDN set in the cert. I haven't tested using IP's in the mongo uri to access the cluster however. If it would be beneficial to you, I could test this...

edgarmarkosov commented 7 years ago

Is there any fix of this issue for mongoose v4.8.4?

wayofthefuture commented 7 years ago

4.5.10 and 4.4.12 doesn't solve the problem for me. Running a google compute replica set with replica set name rs0.

luismendozamx commented 7 years ago

I had the same issue using v4.6.5 upgrading to v4.8.5 solved the issue without changing any config.

wayofthefuture commented 7 years ago

Just tried 4.8.5 no luck :(

edgarmarkosov commented 7 years ago

How do you connect to replica set?

wayofthefuture commented 7 years ago

We are using:

mongodb://root:password@mongo0.dev.domain.com:27017,mongo1.dev.domain.com:27017,mongo2.dev.domain.com:27017/main?replicaSet=rs0&authSource=admin

I've read somewhere it is only required to pass the primary address and the 2 secondaries are not necessary. Is this true? Thanks.

edgarmarkosov commented 7 years ago

Try this. NOTE that there is no need to connect to arbiter mongo, only 2 replicas:

mongoose.connect("mongodb://mongo1.dev.domain.com,mongo2.dev.domain.com/main?replicaSet=rs0&authSource=admin", { user: 'MONGO_USERNAME', pass: 'MONGO_PASSWORD' });

If this will NOT work, then you have some replica config problems, for example maybe the mongo port you are connecting to is closed.

abeven commented 7 years ago

Ran into this error message connecting to a mongo RS in a Kubernetes StatefulSet. Didn't qualify the DNS names in the connection string with the SS name and got the "no primary error".

So for a SS named mongo, "mongo-0" should've been "mongo-0.mongo". Error went away.

wayofthefuture commented 7 years ago

@edgarmarkosov We are not using an arbiter. We are using 3 full instances. It was recommended in the Mongo docs that having 3 full instances was better than 2 with an arbiter. We are using the standard Google Cloud bitnami replica deployment. Pretty much just a few clicks and it is up and running.

I tried connection using your method above but it did not work. I am sure it's some kind of weird problem. I read somewhere that the primary will send the addresses of the other 2 secondaries. I hope that is so, then we can just use the address of the primary in the connection string.