MongoDB not master Error

Background – not master error is returned when writing to secondary mongod. If your application uses connection string with replset it will be good to avoid connecting directly to one member.

As replica set in MongoDB is a group of mongod processes that provide redundancy and high availability. The members of a replica set include primary and secondaries. Although clients cannot write data to secondaries, clients can read data from secondary members. More info are at MongoDB doc.

There are not master error returned if send write operations to secondaries or send read operations to secondaries in non SlaveOK mode.. Different clients have slightly different behaviors, PyMongo and the mongo Shell are covered below. I use some Cloud MongoDB instance, so there is 2497b4e9-57b8-4a68-97f5-c35719ab64e5-1.b2b5a92ee2df47d58bad0fa448c15585.databases.cloud

PyMongo

Write

Write against secondaries would return not master error. Below is an example to connect to MongoDB instance secondary mongod and do write operation.

import ssl
import pprint
from pymongo import MongoClient

myclient = MongoClient('mongodb://username:pwd@2497b4e9-57b8-4a68-97f5-c35719ab64e5-1.b2b5a92ee2df47d58bad0fa448c15585.databases.cloud:32482/mydb1?authSource=admin',ssl=True, ssl_cert_reqs=ssl.CERT_REQUIRED, ssl_ca_certs='797cf5ae-4027-11e9-a020-42025ffb08c8')
mydb = myclient.get_database()
print(mydb.name)
mycol = mydb["book"]
print(mycol.name)
mydict = {"author": "SAN MAO"}
x = mycol.insert_one(mydict).inserted_id
print(x)

Below is the output. The insert is failed, pymongo.errors.NotMasterError: not master error is returned.

mydb1
book
Traceback (most recent call last):
  File "pymongo-test-2.py", line 15, in <module>
    x = mycol.insert_one(mydict).inserted_id
  File "/usr/local/lib/python2.7/site-packages/pymongo/collection.py", line 693, in insert_one
    session=session),
  File "/usr/local/lib/python2.7/site-packages/pymongo/collection.py", line 607, in _insert
    bypass_doc_val, session)
  File "/usr/local/lib/python2.7/site-packages/pymongo/collection.py", line 595, in _insert_one
    acknowledged, _insert_command, session)
  File "/usr/local/lib/python2.7/site-packages/pymongo/mongo_client.py", line 1248, in _retryable_write
    return self._retry_with_session(retryable, func, s, None)
  File "/usr/local/lib/python2.7/site-packages/pymongo/mongo_client.py", line 1201, in _retry_with_session
    return func(session, sock_info, retryable)
  File "/usr/local/lib/python2.7/site-packages/pymongo/collection.py", line 590, in _insert_command
    retryable_write=retryable_write)
  File "/usr/local/lib/python2.7/site-packages/pymongo/pool.py", line 584, in command
    self._raise_connection_failure(error)
  File "/usr/local/lib/python2.7/site-packages/pymongo/pool.py", line 745, in _raise_connection_failure
    raise error
pymongo.errors.NotMasterError: not master

If change MongoClient to connect with the replicaSet or primary mongod, the write will be successful.

Below is replicaSet MongoClient sample, there is replicaSet=replset

myclient = MongoClient('mongodb://username:pwd@2497b4e9-57b8-4a68-97f5-c35719ab64e5-0.b2b5a92ee2df47d58bad0fa448c15585.databases.cloud:32482,2497b4e9-57b8-4a68-97f5-c35719ab64e5-1.b2b5a92ee2df47d58bad0fa448c15585.databases.cloud:32482/mydb1?authSource=admin&replicaSet=replset',ssl=True, ssl_cert_reqs=ssl.CERT_REQUIRED, ssl_ca_certs='797cf5ae-4027-11e9-a020-42025ffb08c8')

Read

pymongo uses read_preferences to define the read preference modes supported by PyMongo.

A read preference is used in three cases:

  • MongoClient connected to a single mongod.
  • MongoClient initialized with the replicaSet option.
  • MongoClient connected to a mongos, with a sharded cluster of replica sets.

Different setting have different read from primary or secondary, details are in the doc.

The mongo Shell

If connect to replset, it will run at primary and read & write are both work fine.

mongo -u username -p pwd --ssl --sslCAFile 797cf5ae-4027-11e9-a020-42025ffb08c8 --authenticationDatabase admin --host replset/2497b4e9-57b8-4a68-97f5-c35719ab64e5-0.b2b5a92ee2df47d58bad0fa448c15585.databases.cloud:32482,2497b4e9-57b8-4a68-97f5-c35719ab64e5-1.b2b5a92ee2df47d58bad0fa448c15585.databases.cloud:32482
replset:PRIMARY> use mydb1
switched to db mydb1
replset:PRIMARY> db.book.find()
{ "_id" : ObjectId("5cac409e77247ca5363338cf"), "author" : "SAN MAO" }
replset:PRIMARY> db.book.insert({"author":"SAN MAO"})
WriteResult({ "nInserted" : 1 })
replset:PRIMARY> db.book.find()
{ "_id" : ObjectId("5cac409e77247ca5363338cf"), "author" : "SAN MAO" }
{ "_id" : ObjectId("5cac40f1219e493fcc964573"), "author" : "SAN MAO" }

If connect to secondary, it requires setSlaveOk() to read from secondary, write is not allowed obviously. Please note that at MongoDB 4.0, the readPref() method for more fine-grained control over read preference in the mongo shell, details are at doc.

mongo -u username -p pwd --ssl --sslCAFile 797cf5ae-4027-11e9-a020-42025ffb08c8 --authenticationDatabase admin --host 2497b4e9-57b8-4a68-97f5-c35719ab64e5-1.b2b5a92ee2df47d58bad0fa448c15585.databases.cloud:32482
MongoDB shell version v4.0.0
connecting to: mongodb://2497b4e9-57b8-4a68-97f5-c35719ab64e5-1.b2b5a92ee2df47d58bad0fa448c15585.databases.cloud:32482/
MongoDB server version: 4.0.6
replset:SECONDARY> use mydb1
switched to db mydb1
replset:SECONDARY> db.book.find()
Error: error: {
	"operationTime" : Timestamp(1554792804, 1),
	"ok" : 0,
	"errmsg" : "not master and slaveOk=false",
	"code" : 13435,
	"codeName" : "NotMasterNoSlaveOk",
	"$clusterTime" : {
		"clusterTime" : Timestamp(1554792804, 1),
		"signature" : {
			"hash" : BinData(0,"F4GTMkvVzRuWPtjJ3hnCZYsbXMU="),
			"keyId" : NumberLong("6674800866463055873")
		}
	}
}
replset:SECONDARY> db.getMongo().setSlaveOk()
replset:SECONDARY> db.book.find()
{ "_id" : ObjectId("5cac409e77247ca5363338cf"), "author" : "SAN MAO" }
{ "_id" : ObjectId("5cac40f1219e493fcc964573"), "author" : "SAN MAO" }
replset:SECONDARY> db.book.insert({"author":"SAN MAO"})
WriteCommandError({
	"operationTime" : Timestamp(1554792824, 1),
	"ok" : 0,
	"errmsg" : "not master",
	"code" : 10107,
	"codeName" : "NotMaster",
	"$clusterTime" : {
		"clusterTime" : Timestamp(1554792824, 1),
		"signature" : {
			"hash" : BinData(0,"dWbM9um3qgsbauHeUCf00E8kj7g="),
			"keyId" : NumberLong("6674800866463055873")
		}
	}
})