diff --git a/src/box/vy_run.c b/src/box/vy_run.c
index 08d0761bf1b8b6923a86bf938778a46351264d9f..a41e9a057ea6298147c9b430caa101382e63fbb8 100644
--- a/src/box/vy_run.c
+++ b/src/box/vy_run.c
@@ -371,6 +371,7 @@ vy_slice_new(int64_t id, struct vy_run *run,
 	slice->id = id;
 	slice->run = run;
 	vy_run_ref(run);
+	run->slice_count++;
 	if (begin != NULL)
 		tuple_ref(begin);
 	slice->begin = begin;
@@ -424,6 +425,8 @@ void
 vy_slice_delete(struct vy_slice *slice)
 {
 	assert(slice->pin_count == 0);
+	assert(slice->run->slice_count > 0);
+	slice->run->slice_count--;
 	vy_run_unref(slice->run);
 	if (slice->begin != NULL)
 		tuple_unref(slice->begin);
@@ -910,8 +913,10 @@ static int
 vy_page_read_cb_free(struct cbus_call_msg *base)
 {
 	struct vy_page_read_task *task = (struct vy_page_read_task *)base;
+	struct vy_run_env *env = task->run->env;
 	vy_page_delete(task->page);
-	mempool_free(&task->run->env->read_task_pool, task);
+	vy_run_unref(task->run);
+	mempool_free(&env->read_task_pool, task);
 	return 0;
 }
 
@@ -970,6 +975,7 @@ vy_run_iterator_load_page(struct vy_run_iterator *itr, uint32_t page_no,
 		task->run = slice->run;
 		task->page_info = *page_info;
 		task->page = page;
+		vy_run_ref(task->run);
 
 		/* Post task to the reader thread. */
 		rc = cbus_call(&reader->reader_pipe, &reader->tx_pipe,
@@ -978,6 +984,7 @@ vy_run_iterator_load_page(struct vy_run_iterator *itr, uint32_t page_no,
 		if (!task->base.complete)
 			return -1; /* timed out or cancelled */
 
+		vy_run_unref(task->run);
 		mempool_free(&env->read_task_pool, task);
 
 		if (rc != 0) {
diff --git a/src/box/vy_run.h b/src/box/vy_run.h
index 6973ee2d30f0cd1fd45e3790676204a36ff4a5e2..b3e3d1c6ff4d112f2a1d28005b4df690c3ed575c 100644
--- a/src/box/vy_run.h
+++ b/src/box/vy_run.h
@@ -130,15 +130,18 @@ struct vy_run {
 	/**
 	 * Run reference counter, the run is deleted once it hits 0.
 	 * A new run is created with the reference counter set to 1.
-	 * A run is referenced by each slice created for it.
+	 * A run is referenced by each slice created for it and each
+	 * pending read or write task.
 	 */
 	int refs;
+	/** Number of slices created for this run. */
+	int slice_count;
 	/**
 	 * Counter used on completion of a compaction task to check if
 	 * all slices of the run have been compacted and so the run is
 	 * not used any more and should be deleted.
 	 */
-	int64_t compacted_slice_count;
+	int compacted_slice_count;
 	/**
 	 * Link in the list of runs that became unused
 	 * after compaction.
diff --git a/src/box/vy_scheduler.c b/src/box/vy_scheduler.c
index b6225ace6ad207bbfb12012c6c15ac926f69a360..4954afe75d4898b9cbb654050fabe1f1badc8bac 100644
--- a/src/box/vy_scheduler.c
+++ b/src/box/vy_scheduler.c
@@ -1102,7 +1102,7 @@ vy_task_compact_complete(struct vy_scheduler *scheduler, struct vy_task *task)
 	}
 	for (slice = first_slice; ; slice = rlist_next_entry(slice, in_range)) {
 		run = slice->run;
-		if (run->compacted_slice_count == run->refs)
+		if (run->compacted_slice_count == run->slice_count)
 			rlist_add_entry(&unused_runs, run, in_unused);
 		slice->run->compacted_slice_count = 0;
 		if (slice == last_slice)
diff --git a/test/vinyl/errinj.result b/test/vinyl/errinj.result
index e7c9bc71ce9e0b7afa7f311701b53301bf08d3bf..91351086658e953b03bf5c718dfe7d4db718d234 100644
--- a/test/vinyl/errinj.result
+++ b/test/vinyl/errinj.result
@@ -290,9 +290,27 @@ s:select()
   - [9, 'test str9']
   - [10, 'test str10']
 ...
+-- index is dropped while a read task is in progress
+errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", 0.05)
+---
+- ok
+...
+f1 = fiber.create(test_cancel_read)
+---
+...
+fiber.cancel(f1)
+---
+...
 s:drop()
 ---
 ...
+fiber.sleep(0.1)
+---
+...
+errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", 0);
+---
+- ok
+...
 box.cfg{vinyl_cache = vinyl_cache}
 ---
 ...
diff --git a/test/vinyl/errinj.test.lua b/test/vinyl/errinj.test.lua
index 7655a57cc4154894237bd5208bb1da5592bb227c..9724a69b82b28f61b42d5de95e45ee0ec3ef4627 100644
--- a/test/vinyl/errinj.test.lua
+++ b/test/vinyl/errinj.test.lua
@@ -101,7 +101,14 @@ errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", 0);
 errinj.set("ERRINJ_VY_READ_PAGE", false);
 s:select()
 
+-- index is dropped while a read task is in progress
+errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", 0.05)
+f1 = fiber.create(test_cancel_read)
+fiber.cancel(f1)
 s:drop()
+fiber.sleep(0.1)
+errinj.set("ERRINJ_VY_READ_PAGE_TIMEOUT", 0);
+
 box.cfg{vinyl_cache = vinyl_cache}
 
 -- gh-2871: check that long reads are logged