{"record":{"id":"bb6022f7012c8c65","repo":"apache/cassandra","slug":"this-cluster-is-migrating-to-cluster-metadata-can-bb6022","errorCode":null,"errorMessage":"This cluster is migrating to cluster metadata, can't abort %s until that is done.","messagePattern":"This cluster is migrating to cluster metadata, can't abort (.+?) until that is done\\.","errorType":"exception","errorClass":"java.lang.IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/tcm/sequences/SingleNodeSequences.java","lineNumber":254,"sourceCode":"        StorageService.instance.clearTransientMode();\n        InProgressSequences.finishInProgressSequences(self);\n    }\n\n    static void abortMove(String nodeId)\n    {\n        abortHelper(nodeId, MultiStepOperation.Kind.MOVE, MOVE_FAILED);\n    }\n\n    /**\n     *\n     * @param nodeId node id to abort the MSO for, null for local node\n     * @param kind the expected kind of the multi step operation to abort\n     * @param ssMode the legacy mode we want storage service to be in, null for any\n     */\n    private static void abortHelper(@Nullable String nodeId, MultiStepOperation.Kind kind, @Nullable StorageService.Mode ssMode)\n    {\n        if (ClusterMetadataService.instance().isMigrating() || ClusterMetadataService.state() == ClusterMetadataService.State.GOSSIP)\n            throw new IllegalStateException(String.format(\"This cluster is migrating to cluster metadata, can't abort %s until that is done.\", kind));\n\n        ClusterMetadata metadata = ClusterMetadata.current();\n        NodeId toAbort = nodeId == null ? metadata.myNodeId() : NodeId.fromString(nodeId);\n        MultiStepOperation<?> sequence = metadata.inProgressSequences.get(toAbort);\n        if (sequence == null || sequence.kind() != kind)\n        {\n            if (toAbort.equals(metadata.myNodeId()) && ssMode != null && StorageService.instance.operationMode() == ssMode)\n            {\n                // there is no ongoing sequence with the given kind, but storage service operation mode is set, clear it\n                logger.debug(\"There is no ongoing {} sequence for this node, but operation mode is {} - clearing transient mode\", kind, ssMode);\n                StorageService.instance.clearTransientMode();\n                return;\n            }\n            else\n            {\n                String msg = String.format(\"No %s operation in progress for %s, can't abort (%s)\", kind, toAbort, sequence);\n                logger.info(msg);\n                throw new IllegalStateException(msg);","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/sequences/SingleNodeSequences.java#L236-L272","documentation":"abortHelper (used by abortDecommission, abortRemoveNode, abortMove) refuses to abort any multi-step operation while the cluster is migrating to Cluster Metadata (isMigrating() or state GOSSIP), throwing IllegalStateException with the operation kind in the message. Aborting topology sequences mid-migration could leave metadata inconsistent.","triggerScenarios":"Running `nodetool abortmove` / `abortdecommission` / `abortremovenode` while ClusterMetadataService.instance().isMigrating() is true or ClusterMetadataService.state() == State.GOSSIP.","commonSituations":"Trying to clean up a stuck topology operation during a rolling upgrade to TCM before migration finishes; abort scripts executed as part of an upgrade runbook too early.","solutions":["Wait for the TCM migration to complete, then run the abort command again.","Find nodes still in GOSSIP/migration state via logs and complete their migration first.","If migration itself is blocked by the stuck operation, resolve the migration blocker per upgrade documentation instead of aborting."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (ClusterMetadataService.instance().isMigrating() || ClusterMetadataService.state() == ClusterMetadataService.State.GOSSIP)\n    return; // defer abort until migration completes","typeGuard":null,"tryCatchPattern":"try { abortMove(nodeId); }\ncatch (IllegalStateException e) { if (e.getMessage().contains(\"migrating\")) { scheduleRetryAfterMigration(); } else throw e; }","preventionTips":["Sequence upgrade and topology-cleanup steps: abort only after migration completes","Verify ClusterMetadataService.state() in abort automation","Resolve migration blockers instead of aborting mid-migration"],"tags":["cassandra","cluster-metadata","migration","abort"],"backgroundTag":"invalid-state-transition","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}