diff --git a/crates/agglayer-storage/src/stores/per_epoch/mod.rs b/crates/agglayer-storage/src/stores/per_epoch/mod.rs index 2bd60f515..cc5c0dbbc 100644 --- a/crates/agglayer-storage/src/stores/per_epoch/mod.rs +++ b/crates/agglayer-storage/src/stores/per_epoch/mod.rs @@ -513,7 +513,24 @@ where &self, index: CertificateIndex, ) -> Result, Error> { - Ok(self.db.get::(&index)?) + match self.db.get::(&index) { + // Epoch DBs created before the proto migration and only reopened + // read-only since were never migrated: read-only opens never create + // column families, so the proto CF is absent here. Fall back to the + // still-present legacy CF, decoding through the same `Certificate::from` + // conversion the migration backfill uses. + Err(crate::storage::DBError::ColumnFamilyNotFound) => { + warn!( + "Proto certificate CF missing for epoch {}: reading from the legacy CF", + self.epoch_number + ); + Ok(self + .db + .get::(&index)? + .map(Certificate::from)) + } + result => Ok(result?), + } } fn get_proof_at_index(&self, index: CertificateIndex) -> Result, Error> { diff --git a/crates/agglayer-storage/src/stores/per_epoch/tests.rs b/crates/agglayer-storage/src/stores/per_epoch/tests.rs index 1d6a6e71d..d469245d1 100644 --- a/crates/agglayer-storage/src/stores/per_epoch/tests.rs +++ b/crates/agglayer-storage/src/stores/per_epoch/tests.rs @@ -228,7 +228,7 @@ fn reopening_epoch_store_migrates_legacy_certificate_rows_to_proto() { } #[test] -fn readonly_epoch_access_requires_migrated_proto_cf() { +fn readonly_epoch_access_falls_back_to_legacy_cf_when_proto_cf_absent() { let tmp = TempDBDir::new(); let config = Arc::new(Config::new(&tmp.path)); let epoch_number = EpochNumber::ZERO; @@ -240,12 +240,18 @@ fn readonly_epoch_access_requires_migrated_proto_cf() { ); let epochs_store = EpochsStore::new(config, pending_store, state_store, BackupClient::noop()).unwrap(); + let expected = sample_data::load_certificate("n15-cert_h0.json"); let legacy = load_v0_certificate_bytes("v0-n15-cert_h0.hex"); let index = CertificateIndex::ZERO; write_raw_epoch_certificate_bytes(&epoch_path, index, legacy); - assert!(epochs_store.get_certificate(epoch_number, index).is_err()); + // The read must fall back to the still-present legacy CF instead of failing + // with `ColumnFamilyNotFound`. + assert_eq!( + epochs_store.get_certificate(epoch_number, index).unwrap(), + Some(expected) + ); } #[rstest]