From 88e00db91c03ac64eeb786f4989f83a173f337bf Mon Sep 17 00:00:00 2001 From: Aleksandra Martyniuk Date: Fri, 20 Feb 2026 11:14:13 +0100 Subject: [PATCH] nodetool: cluster repair: do not fail if a table was dropped nodetool cluster repair without additional params repairs all tablet keyspaces in a cluster. Currently, if a table is dropped while the command is running, all tables are repaired but the command finishes with a failure. Modify nodetool cluster repair. If a table wasn't specified (i.e. all tables are repaired), the command finishes successfully even if a table was dropped. If a table was specified and it does not exist (e.g. because it was dropped before the repair was requested), then the behavior remains unchanged. Fixes: SCYLLADB-568. Closes scylladb/scylladb#28739 (cherry picked from commit 2e68f480682d6c1d99a7365267d706e1f8dd685b) Closes scylladb/scylladb#29280 --- test/nodetool/test_cluster_repair.py | 65 ++++++++++++++++++++++++++++ tools/scylla-nodetool.cc | 3 ++ 2 files changed, 68 insertions(+) diff --git a/test/nodetool/test_cluster_repair.py b/test/nodetool/test_cluster_repair.py index 1603f58a91..ac59ce038a 100644 --- a/test/nodetool/test_cluster_repair.py +++ b/test/nodetool/test_cluster_repair.py @@ -368,3 +368,68 @@ def test_repair_keyspace(nodetool): expected_request("GET", "/storage_service/keyspaces", params={"replication": "tablets"}, response=[]), ]}, ["error processing arguments: nodetool cluster repair repairs only tablet keyspaces. To repair vnode keyspaces use nodetool repair."]) + +def test_cluster_repair_table_dropped(nodetool): + id1 = "ef1b7a61-66c8-494c-bb03-6f65724e6eee" + res = nodetool("cluster", "repair", "ks", expected_requests=[ + expected_request("GET", "/storage_service/keyspaces", response=["ks"]), + expected_request("GET", "/storage_service/keyspaces", params={"replication": "tablets"}, response=["ks"]), + expected_request("GET", "/column_family", response=[{"ks": "ks", "cf": "table1"}, {"ks": "ks", "cf": "table2"}]), + expected_request( + "POST", + "/storage_service/tablets/repair", + params={ + "ks": "ks", + "table": "table1", + "tokens": "all"}, + response={"message": "Can't find a column family table1 in keyspace ks", "code": 400}, response_status=400), + expected_request( + "POST", + "/storage_service/tablets/repair", + params={ + "ks": "ks", + "table": "table2", + "tokens": "all"}, + response={"tablet_task_id": id1}), + expected_request( + "GET", + f"/task_manager/wait_task/{id1}", + response={"state": "done"}), + ]) + + assert _remove_log_timestamp(res.stdout) == f"""\ +Starting repair with task_id={id1} keyspace=ks table=table2 +Repair with task_id={id1} finished +""" + +def test_cluster_repair_specified_table_dropped(nodetool): + id1 = "ef1b7a61-66c8-494c-bb03-6f65724e6eee" + check_nodetool_fails_with_error_contains( + nodetool, + ("cluster", "repair", "ks", "table1", "table2"), + {"expected_requests": [ + expected_request("GET", "/storage_service/keyspaces", response=["ks"]), + expected_request("GET", "/storage_service/keyspaces", params={"replication": "tablets"}, response=["ks"]), + expected_request( + "POST", + "/storage_service/tablets/repair", + params={ + "ks": "ks", + "table": "table1", + "tokens": "all"}, + response={"message": "Can't find a column family table1 in keyspace ks", "code": 400}, response_status=400), + expected_request( + "POST", + "/storage_service/tablets/repair", + params={ + "ks": "ks", + "table": "table2", + "tokens": "all"}, + response={"tablet_task_id": id1}), + expected_request( + "GET", + f"/task_manager/wait_task/{id1}", + response={"state": "done"}), + ] + }, + [f"Can't find a column family table1 in keyspace ks"]) diff --git a/tools/scylla-nodetool.cc b/tools/scylla-nodetool.cc index ed19f774f4..3588550fce 100644 --- a/tools/scylla-nodetool.cc +++ b/tools/scylla-nodetool.cc @@ -583,6 +583,9 @@ void cluster_repair_operation(scylla_rest_client& client, const bpo::variables_m log("Repair with task_id={} finished", task_id); } } catch (const api_request_failed& ex) { + if (tables.empty() && std::string(ex.what()).contains("Can't find a column family")) { + continue; + } log("ERROR: Repair request for keyspace={} table={} failed with {}", keyspace, table, ex); exit_code = EXIT_FAILURE; }