diff --git a/mysql-test/suite/versioning/t/y.opt b/mysql-test/suite/versioning/t/y.opt
new file mode 100644
index 00000000000..a1207721427
--- /dev/null
+++ b/mysql-test/suite/versioning/t/y.opt
@@ -0,0 +1 @@
+--innodb-purge-threads=1
diff --git a/mysql-test/suite/versioning/t/y.test b/mysql-test/suite/versioning/t/y.test
new file mode 100644
index 00000000000..71dd6b309b5
--- /dev/null
+++ b/mysql-test/suite/versioning/t/y.test
@@ -0,0 +1,58 @@
+--source include/have_innodb.inc
+--disable_query_log
+--disable_warnings
+
+--let $datadir= `select @@datadir`
+set @saved_frequency = @@global.innodb_purge_rseg_truncate_frequency;
+set global innodb_purge_rseg_truncate_frequency = 1;
+
+set global debug_dbug="+d,ib_purge_virtual_mdev_16222_1,ib_purge_virtual_mdev_16222_2";
+
+create table t1 (
+  pk serial,
+  vb tinyblob as (b) virtual,
+  b tinyblob,
+  y year,
+  c char(255),
+  primary key(pk),
+  index (y,vb(64))
+) engine=innodb;
+
+insert ignore into t1 (b,y,c) values ('foo',1981,'bar');
+
+select * from t1 into outfile 'load.data';
+load data infile 'load.data' replace into table t1;
+
+set debug_sync= "now WAIT_FOR latch_released";
+set global debug_dbug="-d,ib_purge_virtual_mdev_16222_1";
+drop table t1;
+--remove_file $datadir/test/load.data
+
+set debug_sync= "now SIGNAL drop_started WAIT_FOR got_no_such_table";
+
+create table t1 (
+  pk serial,
+  vb tinyblob as (b) virtual,
+  b tinyblob,
+  y year,
+  c char(255),
+  primary key(pk),
+  index (y,vb(64))
+) engine=innodb;
+
+insert ignore into t1 (b,y,c) values ('foo',1981,'bar');
+
+select * from t1 into outfile 'load.data';
+load data infile 'load.data' replace into table t1;
+
+set debug_sync= "now WAIT_FOR got_no_such_table";
+set global debug_dbug="-d,ib_purge_virtual_mdev_16222_2";
+set debug_sync= "RESET";
+
+# cleanup
+drop table t1;
+--remove_file $datadir/test/load.data
+
+set global innodb_purge_rseg_truncate_frequency = @saved_frequency;
+set global debug_dbug="";
+--echo ok
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 94e2b518fa4..fa03417346c 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -4762,7 +4762,10 @@ TABLE *open_purge_table(THD *thd, const char *db, size_t dblen,
   DBUG_ASSERT(!error || !ot_ctx.can_recover_from_failed_open());
 
   if (unlikely(error))
+  {
     close_thread_tables(thd);
+    thd->clear_error();
+  }
 
   DBUG_RETURN(error ? NULL : tl->table);
 }
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index e93c3cede55..366ddcb4e7e 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -2108,6 +2108,11 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, bool if_exists,
     }
   }
 
+  DBUG_EXECUTE_IF("ib_purge_virtual_mdev_16222_1",
+          DBUG_ASSERT(!debug_sync_set_action(
+                                  thd,
+                                  STRING_WITH_LEN("now SIGNAL drop_started"))););
+
   /* mark for close and remove all cached entries */
   thd->push_internal_handler(&err_handler);
   error= mysql_rm_table_no_locks(thd, tables, if_exists, drop_temporary,
diff --git a/sql/table.cc b/sql/table.cc
index f07ae3018f7..c33ed3d2d3e 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -8256,6 +8256,7 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
 
 int TABLE::update_virtual_field(Field *vf)
 {
+  DBUG_ASSERT(!in_use->is_error());
   Query_arena backup_arena;
   DBUG_ENTER("TABLE::update_virtual_field");
   in_use->set_n_backup_active_arena(expr_arena, &backup_arena);
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 107fcac762a..74da0a4df03 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -20386,6 +20386,8 @@ static TABLE* innodb_acquire_mdl(THD* thd, dict_table_t* table)
 		return NULL;
 	}
 
+	DEBUG_SYNC(thd, "ib_purge_virtual_latch_released");
+
 	const table_id_t table_id = table->id;
 retry_mdl:
 	const bool unaccessible = !table->is_readable() || table->corrupted;
@@ -20397,6 +20399,7 @@ static TABLE* innodb_acquire_mdl(THD* thd, dict_table_t* table)
 
 	TABLE*	mariadb_table = open_purge_table(thd, db_buf, db_buf_len,
 						 tbl_buf, tbl_buf_len);
+	DEBUG_SYNC(thd, "ib_purge_virtual_got_no_such_table");
 
 	table = dict_table_open_on_id(table_id, false, DICT_TABLE_OP_NORMAL);
 
@@ -20446,6 +20449,17 @@ static TABLE* innodb_acquire_mdl(THD* thd, dict_table_t* table)
 for purge thread */
 static TABLE* innodb_find_table_for_vc(THD* thd, dict_table_t* table)
 {
+	DBUG_EXECUTE_IF("ib_purge_virtual_mdev_16222_1",
+		DBUG_ASSERT(!debug_sync_set_action(
+			thd,
+			STRING_WITH_LEN("ib_purge_virtual_latch_released "
+				"SIGNAL latch_released WAIT_FOR drop_started"))););
+	DBUG_EXECUTE_IF("ib_purge_virtual_mdev_16222_2",
+		DBUG_ASSERT(!debug_sync_set_action(
+			thd,
+			STRING_WITH_LEN("ib_purge_virtual_got_no_such_table "
+				"SIGNAL got_no_such_table"))););
+
 	if (THDVAR(thd, background_thread)) {
 		/* Purge thread acquires dict_sys.latch while
 		processing undo log record. Release it
@@ -20781,6 +20795,7 @@ innobase_get_computed_value(
 	dbug_tmp_restore_column_map(mysql_table->write_set, old_write_set);
 
 	if (ret != 0) {
+	// FIXME: Why this error message is macro-hidden?
 #ifdef INNODB_VIRTUAL_DEBUG
 		ib::warn() << "Compute virtual column values failed ";
 		fputs("InnoDB: Cannot compute value for following record ",
