diff --git a/changelogs/unreleased/gh-5843-fiber-wakeup.md b/changelogs/unreleased/gh-5843-fiber-wakeup.md
new file mode 100644
index 0000000000000000000000000000000000000000..f501bc04f2467fecfd6be162d63e9fcb07d828d5
--- /dev/null
+++ b/changelogs/unreleased/gh-5843-fiber-wakeup.md
@@ -0,0 +1,6 @@
+## bugfix/core
+
+* Remove assertion raised in case of `fiber_wakeup()` get called with
+  dead fibers. Due to backward compatibility we've allowed such calls
+  for release builds but not for debug builds. In result there
+  was inconsistency between program behaviour (gh-5843).
diff --git a/src/lib/core/fiber.c b/src/lib/core/fiber.c
index 87a18a6a50d02be6fb8994a5b4ef201fca7281b5..bc9a649dfd7ac2ece1c62ba6ede99c94f019875a 100644
--- a/src/lib/core/fiber.c
+++ b/src/lib/core/fiber.c
@@ -502,14 +502,15 @@ void
 fiber_wakeup(struct fiber *f)
 {
 	/*
-	 * DEAD is checked both in the assertion and in the release build
-	 * because it should not ever happen, at least internally. But in some
-	 * user modules it might happen, and better ignore such fibers.
-	 * Especially since this was allowed for quite some time in the public
-	 * API and need to keep it if it costs nothing, for backward
-	 * compatibility.
+	 * DEAD fiber can be lingering in the cord fiber list
+	 * if it is joinable. And once its execution is complete
+	 * it should be reaped with fiber_join() call.
+	 *
+	 * Still our API allows to call fiber_wakeup() on dead
+	 * joinable fibers so simply ignore it.
 	 */
-	assert((f->flags & FIBER_IS_DEAD) == 0);
+	assert((f->flags & FIBER_IS_DEAD) == 0 ||
+	       (f->flags & FIBER_IS_JOINABLE) != 0);
 	const int no_flags = FIBER_IS_READY | FIBER_IS_DEAD | FIBER_IS_RUNNING;
 	if ((f->flags & no_flags) == 0)
 		fiber_make_ready(f);
diff --git a/test/unit/fiber.cc b/test/unit/fiber.cc
index eb0637f85845bd059ec29774ee73ede69f050cea..09ef30cf1e985207994375259a24f4a8b4001cec 100644
--- a/test/unit/fiber.cc
+++ b/test/unit/fiber.cc
@@ -276,6 +276,21 @@ fiber_wakeup_self_test()
 	footer();
 }
 
+static void
+fiber_wakeup_dead_test()
+{
+	header();
+
+	struct fiber *fiber = fiber_new_xc("wakeup_dead", noop_f);
+	fiber_set_joinable(fiber, true);
+	fiber_start(fiber);
+	fiber_wakeup(fiber);
+	fiber_wakeup(fiber);
+	fiber_join(fiber);
+
+	footer();
+}
+
 static void
 fiber_dead_while_in_cache_test(void)
 {
@@ -343,6 +358,7 @@ main_f(va_list ap)
 	fiber_join_test();
 	fiber_stack_test();
 	fiber_wakeup_self_test();
+	fiber_wakeup_dead_test();
 	fiber_dead_while_in_cache_test();
 	fiber_flags_respect_test();
 	cord_cojoin_test();
diff --git a/test/unit/fiber.result b/test/unit/fiber.result
index a1bf4381823712efbd64983153bf7df36a6f7371..61f5f05dfb862039b28858889d9487de11ddb40e 100644
--- a/test/unit/fiber.result
+++ b/test/unit/fiber.result
@@ -19,6 +19,8 @@ OutOfMemory: Failed to allocate 42 bytes in allocator for exception
 	*** fiber_stack_test: done ***
 	*** fiber_wakeup_self_test ***
 	*** fiber_wakeup_self_test: done ***
+	*** fiber_wakeup_dead_test ***
+	*** fiber_wakeup_dead_test: done ***
 	*** fiber_dead_while_in_cache_test ***
 	*** fiber_dead_while_in_cache_test: done ***
 	*** fiber_flags_respect_test ***