diff --git a/emper/io/Future.hpp b/emper/io/Future.hpp
index 3cda8c91ad9f13bfa3e0a099c1ed6f1c97a4a01b..463cad7bc90fa2dc82fa2566f9ee5420a5d7a3c9 100644
--- a/emper/io/Future.hpp
+++ b/emper/io/Future.hpp
@@ -6,6 +6,7 @@
 #include <sys/socket.h>	 // for socklen_t
 #include <sys/types.h>	 // for ssize_t
 
+#include <cassert>
 #include <cstddef>	// for size_t
 #include <cstdint>	// for int32_t, uint8_t
 #include <cstdlib>	// for abort
@@ -93,6 +94,7 @@ class Future : public Logger<LogSubsystem::IO> {
 	virtual void prepareSqe(io_uring_sqe* sqe) = 0;
 
 	void setCompletion(int32_t res) {
+		assert(!state.completed);
 		LOGD("Complete " << this);
 		returnValue = res;
 		state.completed = true;
diff --git a/tests/LinkFutureTest.cpp b/tests/LinkFutureTest.cpp
index eb7289ba409e9942565882276201dad6f07ee0b8..9a05b0368d8b93f22c982d21b703e5f33ada6fe9 100644
--- a/tests/LinkFutureTest.cpp
+++ b/tests/LinkFutureTest.cpp
@@ -1,14 +1,17 @@
 // SPDX-License-Identifier: LGPL-3.0-or-later
 // Copyright © 2020-2021 Florian Fischer
+#include <fcntl.h>
 #include <sys/eventfd.h>	// for eventfd
 #include <sys/types.h>		// for ssize_t
 
+#include <array>
 #include <cassert>	// for assert
 #include <cerrno>		// for EBADF, ECANCELED
 #include <cstdint>	// for uint64_t, int32_t
 #include <cstdlib>	// for exit, EXIT_SUCCESS
 
-#include "Common.hpp"			// for DIE_MSG_ERRNO, DIE_MSG
+#include "Common.hpp"	 // for DIE_MSG_ERRNO, DIE_MSG
+#include "io.hpp"
 #include "io/Future.hpp"	// for ReadFuture, CloseFuture, WriteFuture
 
 using emper::io::CloseFuture;
@@ -41,12 +44,45 @@ static void successChain() {
 	}
 }
 
-static void failureChain() {
-	// NOLINTNEXTLINE(modernize-avoid-c-arrays)
-	char buf[32];
-	ReadFuture invalidReadFuture(42, &buf, sizeof(buf), 0);
+static void successLoop() {
+	int efd = eventfd(0, 0);
+	if (efd == -1) {
+		DIE_MSG_ERRNO("eventfd failed");
+	}
+
+	const unsigned ITERATIONS = 10000;
+	for (unsigned i = 0; i < ITERATIONS; ++i) {
+		uint64_t write_buf = 42;
+		WriteFuture writeFuture(efd, &write_buf, sizeof(write_buf), 0);
 
-	ReadFuture readFuture(0, &buf, sizeof(buf), 0);
+		uint64_t read_buf;
+		ReadFuture readFuture(efd, &read_buf, sizeof(read_buf), 0);
+		readFuture.setDependency(writeFuture);
+
+		ssize_t res = readFuture.submitAndWait();
+
+		if (res == -1) {
+			DIE_MSG_ERRNO("linked requests chain failed");
+		}
+
+		if (read_buf != 42) {
+			DIE_MSG("dependent read value differs from written value");
+		}
+	}
+
+	CloseFuture closeFuture(efd);
+	ssize_t res = closeFuture.submitAndWait();
+
+	if (res == -1) {
+		DIE_MSG_ERRNO("linked requests chain failed");
+	}
+}
+
+static void failureChainInvCor() {
+	std::array<char, 32> buf;
+	ReadFuture invalidReadFuture(-1, buf.data(), buf.size(), 0);
+
+	ReadFuture readFuture(0, buf.data(), buf.size(), 0);
 	readFuture.setDependency(invalidReadFuture);
 
 	int32_t res = readFuture.submitAndWait();
@@ -56,9 +92,46 @@ static void failureChain() {
 	assert(res == -EBADF);
 }
 
+static void failureChainCorInvCor() {
+	std::array<char, 32> buf;
+
+	int fd = emper::io::openAndWait("/dev/null", O_WRONLY);
+	// int fd = open("/dev/null", O_WRONLY, 0);
+	assert(fd != -1);
+
+	WriteFuture correctFuture1(fd, buf.data(), buf.size(), 0);
+
+	ReadFuture invalidFuture(-1, buf.data(), buf.size(), 0);
+	invalidFuture.setDependency(correctFuture1);
+
+	WriteFuture correctFuture2(fd, buf.data(), buf.size(), 0);
+	correctFuture2.setDependency(invalidFuture);
+
+	int32_t res = correctFuture2.submitAndWait();
+	assert(res == -ECANCELED);
+
+	res = invalidFuture.wait();
+	assert(res == -EBADF);
+
+	res = correctFuture1.wait();
+	assert(res == (int32_t)buf.size());
+
+	emper::io::close(fd);
+}
+
 void emperTest() {
+	// This leaves the io_uring in a weird state because the successChain() afterwards
+	// fails because the write future is already completed with -ECANCELED but
+	// there is successful cqe in the CQ for this future
+	failureChainCorInvCor();
+
 	successChain();
-	failureChain();
+	successLoop();
+	failureChainInvCor();
+
+	// failureChainInvCor left the io_uring in a weird state because
+	// the io_uring_submit of the openAndWait() never returns.
+	// failureChainCorInvCor();
 
 	exit(EXIT_SUCCESS);
 }