diff --git a/src/box/vy_log.c b/src/box/vy_log.c
index 06ab72472f9c57fbad656fc9f4c1e288a546f541..85b61a84cb0b659913a64a6cc9e52ee05682c2f1 100644
--- a/src/box/vy_log.c
+++ b/src/box/vy_log.c
@@ -2141,9 +2141,10 @@ vy_recovery_build_index_id_hash(struct vy_recovery *recovery)
 		/*
 		 * If there's no LSM tree for these space_id/index_id
 		 * or it was dropped, simply replace it with the latest
-		 * LSM tree version.
+		 * committed LSM tree version.
 		 */
-		if (hashed_lsm == NULL || hashed_lsm->drop_lsn >= 0) {
+		if (hashed_lsm == NULL ||
+		    (hashed_lsm->drop_lsn >= 0 && lsm->create_lsn >= 0)) {
 			struct mh_i64ptr_node_t node;
 			node.key = vy_recovery_index_id_hash(space_id, index_id);
 			node.val = lsm;
diff --git a/test/vinyl/errinj_vylog.result b/test/vinyl/errinj_vylog.result
index 0e3b79c4a00643c848656f4e70e2ccbadf7b3dac..06cc68188d7013fe2060e235977434712dde2d0e 100644
--- a/test/vinyl/errinj_vylog.result
+++ b/test/vinyl/errinj_vylog.result
@@ -368,3 +368,58 @@ s.index.sk:select()
 s:drop()
 ---
 ...
+--
+-- gh-4066: recovery error if an instance is restarted while
+-- building an index and there's an index with the same id in
+-- the snapshot.
+--
+fiber = require('fiber')
+---
+...
+s = box.schema.space.create('test', {engine = 'vinyl'})
+---
+...
+_ = s:create_index('pk')
+---
+...
+_ = s:create_index('sk', {parts = {2, 'unsigned'}})
+---
+...
+s.index[1] ~= nil
+---
+- true
+...
+s:replace{1, 2}
+---
+- [1, 2]
+...
+box.snapshot()
+---
+- ok
+...
+s.index.sk:drop()
+---
+...
+-- Log index creation, but never finish building it due to an error injection.
+box.error.injection.set('ERRINJ_VY_READ_PAGE_TIMEOUT', 9000)
+---
+- ok
+...
+_ = fiber.create(function() s:create_index('sk', {parts = {2, 'unsigned'}}) end)
+---
+...
+fiber.sleep(0.01)
+---
+...
+-- Should ignore the incomplete index on recovery.
+test_run:cmd('restart server default')
+s = box.space.test
+---
+...
+s.index[1] == nil
+---
+- true
+...
+s:drop()
+---
+...
diff --git a/test/vinyl/errinj_vylog.test.lua b/test/vinyl/errinj_vylog.test.lua
index ce9e12e5d9a169b98286f0d424fe0f662cea11fd..2936f879c8df64cde54a9771dbd58363a0a904da 100644
--- a/test/vinyl/errinj_vylog.test.lua
+++ b/test/vinyl/errinj_vylog.test.lua
@@ -177,3 +177,31 @@ s.index.pk:select()
 s.index.sk:select()
 
 s:drop()
+
+--
+-- gh-4066: recovery error if an instance is restarted while
+-- building an index and there's an index with the same id in
+-- the snapshot.
+--
+fiber = require('fiber')
+
+s = box.schema.space.create('test', {engine = 'vinyl'})
+_ = s:create_index('pk')
+_ = s:create_index('sk', {parts = {2, 'unsigned'}})
+s.index[1] ~= nil
+s:replace{1, 2}
+box.snapshot()
+
+s.index.sk:drop()
+
+-- Log index creation, but never finish building it due to an error injection.
+box.error.injection.set('ERRINJ_VY_READ_PAGE_TIMEOUT', 9000)
+_ = fiber.create(function() s:create_index('sk', {parts = {2, 'unsigned'}}) end)
+fiber.sleep(0.01)
+
+-- Should ignore the incomplete index on recovery.
+test_run:cmd('restart server default')
+
+s = box.space.test
+s.index[1] == nil
+s:drop()