diff --git a/include/ircd/ctx/promise.h b/include/ircd/ctx/promise.h
index b6083cf51..913710698 100644
--- a/include/ircd/ctx/promise.h
+++ b/include/ircd/ctx/promise.h
@@ -46,6 +46,7 @@ struct ircd::ctx::promise_base
 	static const promise_base *head(const shared_state_base &);
 	static const promise_base *head(const promise_base &);
 	static size_t refcount(const shared_state_base &);
+	static size_t refcount(const promise_base &);
 
 	static promise_base *head(shared_state_base &);
 	static promise_base *head(promise_base &);
diff --git a/ircd/ctx.cc b/ircd/ctx.cc
index 7daa93525..f14ce4c00 100644
--- a/ircd/ctx.cc
+++ b/ircd/ctx.cc
@@ -2058,6 +2058,20 @@ ircd::ctx::promise_base::make_ready()
 	assert(!valid());
 }
 
+/// If no shared state anymore: refcount=0; otherwise the promise
+/// list head from p.st->p resolves to at least &p which means refcount>=1
+size_t
+ircd::ctx::promise_base::refcount(const promise_base &p)
+{
+	const auto ret
+	{
+		p.st? refcount(*p.st): 0UL
+	};
+
+	assert((p.st && ret >= 1) || (!p.st && !ret));
+	return ret;
+}
+
 /// Internal use; returns the number of copies of the promise reachable from
 /// the linked list headed by the shared state. This is used to indicate when
 /// the last copy has destructed which may result in a broken_promise exception