diff --git a/core/util.c b/core/util.c
index 9e53cabf3e6c0f81ac2d941a5fcc62195c5ad4df..d3032fe877f44e529a636c5bf2a0680261dd741e 100644
--- a/core/util.c
+++ b/core/util.c
@@ -107,8 +107,9 @@ xrealloc(void *ptr, size_t size)
 #ifdef ENABLE_BACKTRACE
 
 /*
- * we use global static buffer because it is too late to do
- * any allocation when we are printing bactrace and fiber stack is small
+ * We use a global static buffer because it is too late to do any
+ * allocation when we are printing backtrace and fiber stack is
+ * small.
  */
 
 static char backtrace_buf[4096 * 4];
diff --git a/mod/silverbox/box.c b/mod/silverbox/box.c
index 0432b436a9f604fda40aecae64627ab5f984e235..97d21fe69d52973cf15bc053bf45118b9dfb0775 100644
--- a/mod/silverbox/box.c
+++ b/mod/silverbox/box.c
@@ -268,17 +268,25 @@ prepare_replace(struct box_txn *txn, size_t cardinality, struct tbuf *data)
 #endif
 		lock_tuple(txn, txn->old_tuple);
 	} else {
+		lock_tuple(txn, txn->tuple);
 		/*
-		 * if tuple doesn't exist insert GHOST tuple in indeces
-		 * in order to avoid race condition
-		 * ref count will be incr in commit
+		 * Mark the tuple as ghost before attempting an
+		 * index replace: if it fails, txn_abort() will
+		 * look at the flag and remove the tuple.
+		 */
+		txn->tuple->flags |= GHOST;
+		/*
+		 * If the tuple doesn't exist, insert a GHOST
+		 * tuple in all indices in order to avoid a race
+		 * condition when another INSERT comes along:
+		 * a concurrent INSERT, UPDATE, or DELETE, returns
+		 * an error when meets a ghost tuple.
+		 *
+		 * Tuple reference counter will be incremented in
+		 * txn_commit().
 		 */
-
 		foreach_index(txn->n, index)
 			index->replace(index, NULL, txn->tuple);
-
-		lock_tuple(txn, txn->tuple);
-		txn->tuple->flags |= GHOST;
 	}
 
 	return -1;
diff --git a/mod/silverbox/index.c b/mod/silverbox/index.c
index 268abfd32c328664bcbb7eff61c9a070e910c22a..e31e8c8507c54b71a7ecdcbd5bc14dffb264f530 100644
--- a/mod/silverbox/index.c
+++ b/mod/silverbox/index.c
@@ -101,7 +101,7 @@ field_compare(struct field *f1, struct field *f2, enum field_data_type type)
 			return -1;
 	}
 
-	panic("imposible happend");
+	panic("impossible happened");
 }
 
 
@@ -347,6 +347,9 @@ index_replace_hash_num(struct index *self, struct box_tuple *old_tuple, struct b
 	u32 key_size = load_varint32(&key);
 	u32 num = *(u32 *)key;
 
+	if (key_size != 4)
+		box_raise(ERR_CODE_ILLEGAL_PARAMS, "key is not u32");
+
 	if (old_tuple != NULL) {
 		void *old_key = tuple_field(old_tuple, self->key_field->fieldno);
 		load_varint32(&old_key);
@@ -354,8 +357,6 @@ index_replace_hash_num(struct index *self, struct box_tuple *old_tuple, struct b
 		assoc_delete(int_ptr_map, self->idx.int_hash, old_num);
 	}
 
-	if (key_size != 4)
-		box_raise(ERR_CODE_ILLEGAL_PARAMS, "key is not u32");
 	assoc_replace(int_ptr_map, self->idx.int_hash, num, tuple);
 #ifdef DEBUG
 	say_debug("index_replace_hash_num(self:%p, old_tuple:%p, tuple:%p) key:%i", self, old_tuple,
@@ -370,6 +371,9 @@ index_replace_hash_num64(struct index *self, struct box_tuple *old_tuple, struct
 	u32 key_size = load_varint32(&key);
 	u64 num = *(u64 *)key;
 
+	if (key_size != 8)
+		box_raise(ERR_CODE_ILLEGAL_PARAMS, "key is not u64");
+
 	if (old_tuple != NULL) {
 		void *old_key = tuple_field(old_tuple, self->key_field->fieldno);
 		load_varint32(&old_key);
@@ -377,8 +381,6 @@ index_replace_hash_num64(struct index *self, struct box_tuple *old_tuple, struct
 		assoc_delete(int64_ptr_map, self->idx.int64_hash, old_num);
 	}
 
-	if (key_size != 8)
-		box_raise(ERR_CODE_ILLEGAL_PARAMS, "key is not u64");
 	assoc_replace(int64_ptr_map, self->idx.int64_hash, num, tuple);
 #ifdef DEBUG
 	say_debug("index_replace_hash_num(self:%p, old_tuple:%p, tuple:%p) key:%"PRIu64, self, old_tuple,
@@ -391,6 +393,9 @@ index_replace_hash_str(struct index *self, struct box_tuple *old_tuple, struct b
 {
 	void *key = tuple_field(tuple, self->key_field->fieldno);
 
+	if (key == NULL)
+		box_raise(ERR_CODE_ILLEGAL_PARAMS, "Supplied tuple misses a field which is part of an index");
+
 	if (old_tuple != NULL) {
 		void *old_key = tuple_field(old_tuple, self->key_field->fieldno);
 		assoc_delete(lstr_ptr_map, self->idx.str_hash, old_key);
@@ -407,6 +412,9 @@ index_replace_hash_str(struct index *self, struct box_tuple *old_tuple, struct b
 static void
 index_replace_tree_str(struct index *self, struct box_tuple *old_tuple, struct box_tuple *tuple)
 {
+	if (tuple->cardinality < self->field_cmp_order_cnt)
+		box_raise(ERR_CODE_ILLEGAL_PARAMS, "Supplied tuple misses a field which is part of an index");
+
 	struct tree_index_member *member = tuple2tree_index_member(self, tuple, NULL);
 
 	if (old_tuple)
diff --git a/test/box_big/sql.result b/test/box_big/sql.result
index 0aacd2ae1b46e7d498f66e35bea217886025a90e..1e57a1e562278586922cd9cb82717b0656f06a4f 100644
--- a/test/box_big/sql.result
+++ b/test/box_big/sql.result
@@ -1,8 +1,8 @@
-
-A test case for Bug#729758
-"SELECT fails with a disjunct and small LIMIT"
-https://bugs.launchpad.net/tarantool/+bug/729758
-
+#
+# A test case for Bug#729758
+# "SELECT fails with a disjunct and small LIMIT"
+# https://bugs.launchpad.net/tarantool/+bug/729758
+#
 insert into t0 values ('Doe', 'Richard')
 Insert OK, 1 row affected
 insert into t0 values ('Roe', 'Richard')
@@ -26,11 +26,11 @@ Found 5 tuples:
 ['Woe', 'Richard']
 ['Major', 'Tomas']
 ['Kytes', 'Tomas']
-
-A test case for Bug#729879
-"Zero limit is treated the same as no limit"
-https://bugs.launchpad.net/tarantool/+bug/729879
-
+#
+# A test case for Bug#729879
+# "Zero limit is treated the same as no limit"
+# https://bugs.launchpad.net/tarantool/+bug/729879
+#
 select * from t0 where k1='Richard' or k1='Tomas' limit 0
 No match
 delete from t0 where k0='Doe'
@@ -49,3 +49,31 @@ delete from t0 where k0='Wales'
 Delete OK, 1 row affected
 delete from t0 where k0='Callaghan'
 Delete OK, 1 row affected
+#
+# A test case for Bug#730593
+# "Bad data if incomplete tuple"
+# https://bugs.launchpad.net/tarantool/+bug/730593
+# Verify that if there is an index on, say, field 2,
+# we can't insert tuples with cardinality 1 and
+# get away with it.
+#
+insert into t0 values ('Britney')
+An error occurred: ERR_CODE_ILLEGAL_PARAMS, 'Illegal parameters'
+select * from t0 where k1='Anything'
+No match
+insert into t0 values ('Stephanie')
+An error occurred: ERR_CODE_ILLEGAL_PARAMS, 'Illegal parameters'
+select * from t0 where k1='Anything'
+No match
+insert into t0 values ('Spears', 'Britney')
+Insert OK, 1 row affected
+select * from t0 where k0='Spears'
+Found 1 tuple:
+['Spears', 'Britney']
+select * from t0 where k1='Anything'
+No match
+select * from t0 where k1='Britney'
+Found 1 tuple:
+['Spears', 'Britney']
+delete from t0 where k0='Spears'
+Delete OK, 1 row affected
diff --git a/test/box_big/sql.test b/test/box_big/sql.test
index 5d94e8911db648736450ce5e13640cbd75fce905..c49825c0e71132426af794fa8e5afff9e4ab5ed1 100644
--- a/test/box_big/sql.test
+++ b/test/box_big/sql.test
@@ -1,10 +1,10 @@
 # encoding: tarantool
 #
-print """
-A test case for Bug#729758
-"SELECT fails with a disjunct and small LIMIT"
-https://bugs.launchpad.net/tarantool/+bug/729758
-"""
+print """#
+# A test case for Bug#729758
+# "SELECT fails with a disjunct and small LIMIT"
+# https://bugs.launchpad.net/tarantool/+bug/729758
+#"""
 
 exec sql "insert into t0 values ('Doe', 'Richard')"
 exec sql "insert into t0 values ('Roe', 'Richard')"
@@ -16,11 +16,11 @@ exec sql "insert into t0 values ('Wales', 'Tomas')"
 exec sql "insert into t0 values ('Callaghan', 'Tomas')"
 exec sql "select * from t0 where k1='Richard' or k1='Tomas' or k1='Tomas' limit 5"
 
-print """
-A test case for Bug#729879
-"Zero limit is treated the same as no limit"
-https://bugs.launchpad.net/tarantool/+bug/729879
-"""
+print """#
+# A test case for Bug#729879
+# "Zero limit is treated the same as no limit"
+# https://bugs.launchpad.net/tarantool/+bug/729879
+#"""
 exec sql "select * from t0 where k1='Richard' or k1='Tomas' limit 0"
 
 # Cleanup
@@ -32,4 +32,22 @@ exec sql "delete from t0 where k0='Kytes'"
 exec sql "delete from t0 where k0='Stiles'"
 exec sql "delete from t0 where k0='Wales'"
 exec sql "delete from t0 where k0='Callaghan'"
+
+print """#
+# A test case for Bug#730593
+# "Bad data if incomplete tuple"
+# https://bugs.launchpad.net/tarantool/+bug/730593
+# Verify that if there is an index on, say, field 2,
+# we can't insert tuples with cardinality 1 and
+# get away with it.
+#"""
+exec sql "insert into t0 values ('Britney')"
+exec sql "select * from t0 where k1='Anything'"
+exec sql "insert into t0 values ('Stephanie')"
+exec sql "select * from t0 where k1='Anything'"
+exec sql "insert into t0 values ('Spears', 'Britney')"
+exec sql "select * from t0 where k0='Spears'"
+exec sql "select * from t0 where k1='Anything'"
+exec sql "select * from t0 where k1='Britney'"
+exec sql "delete from t0 where k0='Spears'"
 # vim: syntax=python
diff --git a/test/lib/test_suite.py b/test/lib/test_suite.py
index 1b04d6a3ea985dc27d7ebbca361ce5b6eb81db89..10f692ee83daaa7accc09377c6c26d882b303fdc 100644
--- a/test/lib/test_suite.py
+++ b/test/lib/test_suite.py
@@ -219,6 +219,7 @@ class TestSuite:
     try:
       server = Server(self.ini["core"], self.ini["module"])
     except Exception as e:
+      print e
       raise RuntimeError("Unknown server: core = {0}, module = {1}".format(
         self.ini["core"], self.ini["module"]))
     server.deploy(self.ini["config"],