diff --git a/substrate/client/consensus/beefy/src/lib.rs b/substrate/client/consensus/beefy/src/lib.rs
index 72df3cab85503960936f161165a8fadb3d7742a4..89a5d51c88702df76f7e3f0e7bb4f65076531066 100644
--- a/substrate/client/consensus/beefy/src/lib.rs
+++ b/substrate/client/consensus/beefy/src/lib.rs
@@ -33,7 +33,7 @@ use crate::{
 	worker::PersistedState,
 };
 use futures::{stream::Fuse, StreamExt};
-use log::{error, info};
+use log::{debug, error, info};
 use parking_lot::Mutex;
 use prometheus::Registry;
 use sc_client_api::{Backend, BlockBackend, BlockchainEvents, FinalityNotifications, Finalizer};
@@ -428,7 +428,7 @@ where
 			let best_beefy = *header.number();
 			// If no session boundaries detected so far, just initialize new rounds here.
 			if sessions.is_empty() {
-				let active_set = expect_validator_set(runtime, backend, &header, beefy_genesis)?;
+				let active_set = expect_validator_set(runtime, backend, &header)?;
 				let mut rounds = Rounds::new(best_beefy, active_set);
 				// Mark the round as already finalized.
 				rounds.conclude(best_beefy);
@@ -447,7 +447,7 @@ where
 
 		if *header.number() == beefy_genesis {
 			// We've reached BEEFY genesis, initialize voter here.
-			let genesis_set = expect_validator_set(runtime, backend, &header, beefy_genesis)?;
+			let genesis_set = expect_validator_set(runtime, backend, &header)?;
 			info!(
 				target: LOG_TARGET,
 				"🥩 Loading BEEFY voter state from genesis on what appears to be first startup. \
@@ -532,7 +532,6 @@ fn expect_validator_set<B, BE, R>(
 	runtime: &R,
 	backend: &BE,
 	at_header: &B::Header,
-	beefy_genesis: NumberFor<B>,
 ) -> ClientResult<ValidatorSet<AuthorityId>>
 where
 	B: Block,
@@ -540,6 +539,7 @@ where
 	R: ProvideRuntimeApi<B>,
 	R::Api: BeefyApi<B, AuthorityId>,
 {
+	debug!(target: LOG_TARGET, "🥩 Try to find validator set active at header: {:?}", at_header);
 	runtime
 		.runtime_api()
 		.validator_set(at_header.hash())
@@ -550,14 +550,14 @@ where
 			// Digest emitted when validator set active 'at_header' was enacted.
 			let blockchain = backend.blockchain();
 			let mut header = at_header.clone();
-			while *header.number() >= beefy_genesis {
+			loop {
+				debug!(target: LOG_TARGET, "🥩 look for auth set change digest in header number: {:?}", *header.number());
 				match worker::find_authorities_change::<B>(&header) {
 					Some(active) => return Some(active),
 					// Move up the chain.
 					None => header = blockchain.expect_header(*header.parent_hash()).ok()?,
 				}
 			}
-			None
 		})
 		.ok_or_else(|| ClientError::Backend("Could not find initial validator set".into()))
 }
diff --git a/substrate/client/consensus/beefy/src/tests.rs b/substrate/client/consensus/beefy/src/tests.rs
index 90b63c9cd44627ccbabfa0d35b1f12c8237b6d50..902feca163983c594baa54f01688ad183c171a03 100644
--- a/substrate/client/consensus/beefy/src/tests.rs
+++ b/substrate/client/consensus/beefy/src/tests.rs
@@ -247,7 +247,7 @@ impl TestNetFactory for BeefyTestNet {
 #[derive(Clone)]
 pub(crate) struct TestApi {
 	pub beefy_genesis: u64,
-	pub validator_set: BeefyValidatorSet,
+	pub validator_set: Option<BeefyValidatorSet>,
 	pub mmr_root_hash: MmrRootHash,
 	pub reported_equivocations:
 		Option<Arc<Mutex<Vec<EquivocationProof<NumberFor<Block>, AuthorityId, Signature>>>>>,
@@ -261,7 +261,7 @@ impl TestApi {
 	) -> Self {
 		TestApi {
 			beefy_genesis,
-			validator_set: validator_set.clone(),
+			validator_set: Some(validator_set.clone()),
 			mmr_root_hash,
 			reported_equivocations: None,
 		}
@@ -270,7 +270,7 @@ impl TestApi {
 	pub fn with_validator_set(validator_set: &BeefyValidatorSet) -> Self {
 		TestApi {
 			beefy_genesis: 1,
-			validator_set: validator_set.clone(),
+			validator_set: Some(validator_set.clone()),
 			mmr_root_hash: GOOD_MMR_ROOT,
 			reported_equivocations: None,
 		}
@@ -300,7 +300,7 @@ sp_api::mock_impl_runtime_apis! {
 		}
 
 		fn validator_set() -> Option<BeefyValidatorSet> {
-			Some(self.inner.validator_set.clone())
+			self.inner.validator_set.clone()
 		}
 
 		fn submit_report_equivocation_unsigned_extrinsic(
@@ -1188,6 +1188,54 @@ async fn should_initialize_voter_at_latest_finalized() {
 	assert_eq!(state, persisted_state);
 }
 
+#[tokio::test]
+async fn should_initialize_voter_at_custom_genesis_when_state_unavailable() {
+	let keys = &[BeefyKeyring::Alice];
+	let validator_set = ValidatorSet::new(make_beefy_ids(keys), 0).unwrap();
+	let mut net = BeefyTestNet::new(1);
+	let backend = net.peer(0).client().as_backend();
+	// custom pallet genesis is block number 7
+	let custom_pallet_genesis = 7;
+	let mut api = TestApi::new(custom_pallet_genesis, &validator_set, GOOD_MMR_ROOT);
+	// remove validator set from `TestApi`, practically simulating unavailable/pruned runtime state
+	api.validator_set = None;
+
+	// push 30 blocks with `AuthorityChange` digests every 5 blocks
+	let hashes = net.generate_blocks_and_sync(30, 5, &validator_set, false).await;
+	let mut finality = net.peer(0).client().as_client().finality_notification_stream().fuse();
+	// finalize 30 without justifications
+	net.peer(0).client().as_client().finalize_block(hashes[30], None).unwrap();
+
+	// load persistent state - nothing in DB, should init at genesis
+	let persisted_state = voter_init_setup(&mut net, &mut finality, &api).await.unwrap();
+
+	// Test initialization at session boundary.
+	// verify voter initialized with all sessions pending, first one starting at block 5 (start of
+	// session containing `custom_pallet_genesis`).
+	let sessions = persisted_state.voting_oracle().sessions();
+	// should have enqueued 6 sessions (every 5 blocks from 5 to 30)
+	assert_eq!(sessions.len(), 6);
+	assert_eq!(sessions[0].session_start(), 7);
+	assert_eq!(sessions[1].session_start(), 10);
+	assert_eq!(sessions[2].session_start(), 15);
+	assert_eq!(sessions[3].session_start(), 20);
+	assert_eq!(sessions[4].session_start(), 25);
+	assert_eq!(sessions[5].session_start(), 30);
+	let rounds = persisted_state.active_round().unwrap();
+	assert_eq!(rounds.session_start(), custom_pallet_genesis);
+	assert_eq!(rounds.validator_set_id(), validator_set.id());
+
+	// verify next vote target is mandatory block 7 (genesis)
+	assert_eq!(persisted_state.best_beefy_block(), 0);
+	assert_eq!(persisted_state.best_grandpa_number(), 30);
+	assert_eq!(persisted_state.voting_oracle().voting_target(), Some(custom_pallet_genesis));
+
+	// verify state also saved to db
+	assert!(verify_persisted_version(&*backend));
+	let state = load_persistent(&*backend).unwrap().unwrap();
+	assert_eq!(state, persisted_state);
+}
+
 #[tokio::test]
 async fn beefy_finalizing_after_pallet_genesis() {
 	sp_tracing::try_init_simple();