diff --git a/src/box/vy_log.c b/src/box/vy_log.c
index b2dcf5fa731db6757ebce036efb0d9b15660ed74..be50b357bbe59aa335268f6bd50631f6a856d198 100644
--- a/src/box/vy_log.c
+++ b/src/box/vy_log.c
@@ -848,6 +848,15 @@ vy_log_next_id(void)
 int
 vy_log_bootstrap(void)
 {
+	/*
+	 * Scan the directory to make sure there is no
+	 * vylog files left from previous setups.
+	 */
+	if (xdir_scan(&vy_log.dir) < 0 && errno != ENOENT)
+		return -1;
+	if (xdir_last_vclock(&vy_log.dir, NULL) >= 0)
+		panic("vinyl directory is not empty");
+
 	/* Add initial vclock to the xdir. */
 	struct vclock *vclock = malloc(sizeof(*vclock));
 	if (vclock == NULL) {
diff --git a/test/box-tap/cfg.test.lua b/test/box-tap/cfg.test.lua
index ace2b41cb44227e05f87777c25a4249b59ddbbf3..2106e192e582e2752f56be07f325d27fcc0f7522 100755
--- a/test/box-tap/cfg.test.lua
+++ b/test/box-tap/cfg.test.lua
@@ -4,7 +4,7 @@ local tap = require('tap')
 local test = tap.test('cfg')
 local socket = require('socket')
 local fio = require('fio')
-test:plan(70)
+test:plan(71)
 
 --------------------------------------------------------------------------------
 -- Invalid values
@@ -367,5 +367,23 @@ os.exit(cnt1 < cnt2 - 8 and 0 or 1)
 ]]
 test:is(run_script(code), 0, "wal_max_size xlog rotation")
 
+--
+-- gh-2872 bootstrap is aborted if vinyl_dir contains vylog files
+-- left from previous runs
+--
+vinyl_dir = fio.tempdir()
+run_script(string.format([[
+box.cfg{vinyl_dir = '%s'}
+s = box.schema.space.create('test', {engine = 'vinyl'})
+s:create_index('pk')
+os.exit(0)
+]], vinyl_dir))
+code = string.format([[
+box.cfg{vinyl_dir = '%s'}
+os.exit(0)
+]], vinyl_dir)
+test:is(run_script(code), PANIC, "bootstrap from non-empty vinyl_dir")
+fio.rmdir(vinyl_dir)
+
 test:check()
 os.exit(0)