{"record":{"id":"7087aabcb59ad700","repo":"apache/cassandra","slug":"cannot-assassinate-the-node-when-sequence-of-kind","errorCode":null,"errorMessage":"Cannot assassinate the node when sequence of kind ${sequenceKind} is in progress. Run abortbootstrap instead.","messagePattern":"Cannot assassinate the node when sequence of kind (.+?) is in progress\\. Run abortbootstrap instead\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/tools/CMSOfflineTool.java","lineNumber":364,"sourceCode":"        private String outputFilePath;\n\n        @Override\n        protected void execute(Output output) throws IOException\n        {\n            ClusterMetadata metadata = parseClusterMetadata();\n            NodeId nodeId = nodeIdentifierOption.getNodeId(metadata);\n\n            // Check if there are any in-progress sequences for given node\n            // If any, then cancel the sequence and then assassinate it\n            if (metadata.inProgressSequences.contains(nodeId))\n            {\n                MultiStepOperation<?> multiStepOperation = metadata.inProgressSequences.get(nodeId);\n                MultiStepOperation.Kind sequenceKind = multiStepOperation.kind();\n                if (!supportedCancelSequences.contains(sequenceKind))\n                {\n                    if (sequenceKind == MultiStepOperation.Kind.JOIN || sequenceKind == MultiStepOperation.Kind.REPLACE)\n                    {\n                        throw new IllegalArgumentException(\"Cannot assassinate the node when sequence of kind \" +\n                                                           sequenceKind + \" is in progress. \" +\n                                                           \"Run abortbootstrap instead.\");\n                    }\n                    else\n                    {\n                        throw new IllegalArgumentException(\"Cannot assassinate the node when sequence of kind \" +\n                                                           sequenceKind + \" is in progress.\");\n                    }\n                }\n\n                output.out.printf(\"Cancelling in-progress sequence of kind %s before assassinating node.\\n\",\n                                  metadata.inProgressSequences.get(nodeId).kind());\n                metadata = new CancelInProgressSequence(nodeId).execute(metadata).success().metadata;\n            }\n\n            metadata = maybeReconfigureCMS(metadata, nodeId);\n            Assassinate transformation = new Assassinate(nodeId, ClusterMetadataService.instance().placementProvider());\n            ClusterMetadata updatedMetadata = transformation.execute(metadata).success().metadata;","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tools/CMSOfflineTool.java#L346-L382","documentation":"The assassinate (force-remove) path of CMSOfflineTool refuses to run when the target node has a JOIN or REPLACE sequence in progress, since those are handled by the dedicated abortbootstrap command. Throwing this IllegalArgumentException steers the operator to the correct tool.","triggerScenarios":"Calling the assassinate operation in `execute` when metadata.inProgressSequences.get(nodeId) is non-null and its kind() equals MultiStepOperation.Kind.JOIN or Kind.REPLACE (i.e. not in supportedCancelSequences).","commonSituations":"Operator tries to force-remove a node that was mid-bootstrap or mid-replace when the cluster went down; normal decommission failed and the operator reaches for assassinate without first aborting the bootstrap.","solutions":["Run `abortbootstrap` for the node first to clear the JOIN/REPLACE sequence, then retry assassinate.","Bring the node back and let the join/replace complete, then decommission normally.","If abortbootstrap is unavailable offline, restore the cluster and use the online cms/ndtool abort flow."],"exampleFix":"// before\nbin/cms assassinate <ip>\n// after\nbin/nodetool abortbootstrap <ip>   # or cms abortbootstrap\nbin/cms assassinate <ip>","handlingStrategy":"validation","validationCode":"MultiStepOperation<?> op = meta.inProgressSequences.get(nodeId);\nif (op != null && (op.kind() == MultiStepOperation.Kind.JOIN || op.kind() == MultiStepOperation.Kind.REPLACE))\n    throw new IllegalStateException(\"Use abortbootstrap for kind \" + op.kind() + \" instead of assassinate\");","typeGuard":null,"tryCatchPattern":"try { tool.assassinate(nodeId); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"Run abortbootstrap\")) { runAbortBootstrap(nodeId); } else throw e; }","preventionTips":["For mid-bootstrap/mid-replace nodes, always reach for abortbootstrap before assassinate.","List in-progress sequences before force-removing any node.","Document the assassinate-vs-abortbootstrap decision in runbooks."],"tags":["assassinate","join-in-progress","replace-in-progress","cms"],"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-17T15:17:12.973Z"}