From e95689c96b5acfc358efbcd2df4af82034aa0fd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20J=C4=99drzejczak?= Date: Mon, 26 Jan 2026 12:47:09 +0100 Subject: [PATCH] storage_proxy: skip validate_read_replica in maintenance mode In maintenance mode, the local node adds only itself to the topology. However, the effective replication map of a keyspace with tablets enabled contains all tablet replicas. It gets them from the tablets map, not the topology. Hence, `network_topology_strategy::sanity_check_read_replicas` hits ``` throw std::runtime_error(format("Requested location for node {} not in topology. backtrace {}", id, lazy_backtrace())); ``` for tablet replicas other than the local node. As a result, all requests to a keyspace with tablets enabled and RF > 1 fail in debug mode (`validate_read_replica` does nothing in other modes). We don't want to skip maintenance mode tests in debug mode, so we skip the check in maintenance mode. We move the `is_debug_build()` check because: - `validate_read_replicas` is a static function with no access to the config, - we want the `!_db.local().get_config().maintenance_mode()` check to be dropped by the compiler in non-debug builds. We also suppress `-Wunneeded-internal-declaration` with `[[maybe_unused]]`. (cherry picked from commit 9d4a5ade0873836d6c00e379331640dbad5bde92) --- service/storage_proxy.cc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/service/storage_proxy.cc b/service/storage_proxy.cc index 1821988e97..de52d059dd 100644 --- a/service/storage_proxy.cc +++ b/service/storage_proxy.cc @@ -123,12 +123,7 @@ utils::small_vector addr_vector_to_id(const gms::gossiper& // Check the effective replication map consistency: // we have an inconsistent effective replication map in case we the number of // read replicas is higher than the replication factor. -void validate_read_replicas(const locator::effective_replication_map& erm, const host_id_vector_replica_set& read_replicas) { - // Skip for non-debug builds. - if constexpr (!tools::build_info::is_debug_build()) { - return; - } - +[[maybe_unused]] void validate_read_replicas(const locator::effective_replication_map& erm, const host_id_vector_replica_set& read_replicas) { const sstring error = erm.get_replication_strategy().sanity_check_read_replicas(erm, read_replicas); if (!error.empty()) { on_internal_error(slogger, error); @@ -6972,7 +6967,12 @@ host_id_vector_replica_set storage_proxy::get_endpoints_for_reading(const schema return host_id_vector_replica_set{my_host_id(erm)}; } auto endpoints = erm.get_replicas_for_reading(token); - validate_read_replicas(erm, endpoints); + // Skip for non-debug builds and maintenance mode. + if constexpr (tools::build_info::is_debug_build()) { + if (!_db.local().get_config().maintenance_mode()) { + validate_read_replicas(erm, endpoints); + } + } auto it = std::ranges::remove_if(endpoints, std::not_fn(std::bind_front(&storage_proxy::is_alive, this, std::cref(erm)))).begin(); endpoints.erase(it, endpoints.end()); sort_endpoints_by_proximity(erm, endpoints);