@@ -37,8 +37,9 @@ use futures::future::BoxFuture;
3737use mz_build_info:: { BuildInfo , DUMMY_BUILD_INFO } ;
3838use mz_catalog:: builtin:: {
3939 BUILTIN_LOOKUP , Builtin , Fingerprint , MZ_CATALOG_RAW , MZ_CATALOG_RAW_DESCRIPTION ,
40- MZ_OBJECT_ARRANGEMENT_SIZE_HISTORY_DESCRIPTION , MZ_STORAGE_USAGE_BY_SHARD ,
41- MZ_STORAGE_USAGE_BY_SHARD_DESCRIPTION , RUNTIME_ALTERABLE_FINGERPRINT_SENTINEL ,
40+ MZ_CLUSTER_REPLICA_FRONTIERS_DESCRIPTION , MZ_OBJECT_ARRANGEMENT_SIZE_HISTORY_DESCRIPTION ,
41+ MZ_STORAGE_USAGE_BY_SHARD , MZ_STORAGE_USAGE_BY_SHARD_DESCRIPTION ,
42+ RUNTIME_ALTERABLE_FINGERPRINT_SENTINEL ,
4243} ;
4344use mz_catalog:: config:: BuiltinItemMigrationConfig ;
4445use mz_catalog:: durable:: objects:: SystemObjectUniqueIdentifier ;
@@ -758,6 +759,15 @@ impl Migration {
758759 "mz_catalog_raw cannot be migrated"
759760 ) ;
760761
762+ // The 0dt caught-up gate reads the leader's `mz_cluster_replica_frontiers` shard for
763+ // the live frontiers it checks every collection against. Migrating it via `Replacement`
764+ // hands us a fresh shard we write ourselves, so the gate would compare us against
765+ // ourselves instead of against the leader.
766+ assert_ne ! (
767+ & * MZ_CLUSTER_REPLICA_FRONTIERS_DESCRIPTION , object,
768+ "mz_cluster_replica_frontiers cannot be migrated or else the 0dt caught-up gate loses its live-frontier reference"
769+ ) ;
770+
761771 let Some ( object_info) = self . system_objects . get ( object) else {
762772 panic ! ( "migration step for non-existent builtin: {object:?}" ) ;
763773 } ;
0 commit comments