diff --git a/src/box/box.cc b/src/box/box.cc
index c43982f5efdf30e49bd5f9d2d23c9896dd0a77a1..67cf1d363b9ef5587e5148fa3180fb37a9bb7e46 100644
--- a/src/box/box.cc
+++ b/src/box/box.cc
@@ -649,6 +649,9 @@ box_upsert(uint32_t space_id, uint32_t index_id, const char *tuple,
 static void
 box_on_cluster_join(const tt_uuid *server_uuid)
 {
+	if (is_ro)
+		tnt_raise(LoggedError, ER_READONLY);
+
 	/** Find the largest existing server id. */
 	struct space *space = space_cache_find(BOX_CLUSTER_ID);
 	class MemtxIndex *index = index_find_system(space, 0);
@@ -669,11 +672,15 @@ box_on_cluster_join(const tt_uuid *server_uuid)
 void
 box_process_join(int fd, struct xrow_header *header)
 {
+	assert(header->type == IPROTO_JOIN);
+
 	/* Check permissions */
 	access_check_universe(PRIV_R);
 	access_check_space(space_cache_find(BOX_CLUSTER_ID), PRIV_W);
 
-	assert(header->type == IPROTO_JOIN);
+	/* Check that we actually can register a new replica */
+	if (is_ro)
+		tnt_raise(LoggedError, ER_READONLY);
 
 	/* Process JOIN request via a replication relay */
 	relay_join(fd, header, recovery->server_id,
diff --git a/test/replication-py/cluster.result b/test/replication-py/cluster.result
index 8f0de85a59bb0a43950827f7883ded0087f9dbd7..c84116802af6d67150ac981493d4661ddf746333 100644
--- a/test/replication-py/cluster.result
+++ b/test/replication-py/cluster.result
@@ -263,6 +263,10 @@ box.info.vclock[10] == nil
 - true
 ...
 -------------------------------------------------------------
+JOIN replica to read-only master
+-------------------------------------------------------------
+'ER_READONLY' exists in server log
+-------------------------------------------------------------
 Cleanup
 -------------------------------------------------------------
 box.schema.user.revoke('guest', 'replication')
diff --git a/test/replication-py/cluster.test.py b/test/replication-py/cluster.test.py
index 86c7a494dfc097c5a37f607a17dbbaa2817c74ca..73ced6b8220c3a31db0e4b238a9ceada2be211d0 100644
--- a/test/replication-py/cluster.test.py
+++ b/test/replication-py/cluster.test.py
@@ -242,6 +242,23 @@ replica.admin('box.info.server.ro')
 replica.admin('box.info.server.lsn == -1')
 replica.admin('box.info.vclock[%d] == nil' % replica_id2)
 
+print '-------------------------------------------------------------'
+print 'JOIN replica to read-only master'
+print '-------------------------------------------------------------'
+
+#gh-1230 Assertion vclock_has on attempt to JOIN read-only master
+failed = TarantoolServer(server.ini)
+failed.script = 'replication-py/failed.lua'
+failed.vardir = server.vardir
+failed.rpl_master = replica
+failed.name = "failed"
+try:
+    failed.deploy()
+except Exception as e:
+    line = "ER_READONLY"
+    if failed.logfile_pos.seek_once(line) >= 0:
+        print "'%s' exists in server log" % line
+
 print '-------------------------------------------------------------'
 print 'Cleanup'
 print '-------------------------------------------------------------'
diff --git a/test/replication-py/failed.lua b/test/replication-py/failed.lua
new file mode 100644
index 0000000000000000000000000000000000000000..3a08208e065f353d7999aebea94592b85e5133c5
--- /dev/null
+++ b/test/replication-py/failed.lua
@@ -0,0 +1,9 @@
+#!/usr/bin/env tarantool
+
+box.cfg({
+    listen              = os.getenv("LISTEN"),
+    replication_source  = os.getenv("MASTER"),
+    slab_alloc_arena    = 0.1,
+})
+
+require('console').listen(os.getenv('ADMIN'))