{"record":{"id":"920bef89242cea11","repo":"apache/cassandra","slug":"can-t-abort-a-s-operation-unless-it-has-failed","errorCode":null,"errorMessage":"Can't abort a %s operation unless it has failed","messagePattern":"Can't abort a (.+?) operation unless it has failed","errorType":"exception","errorClass":"java.lang.IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/tcm/sequences/SingleNodeSequences.java","lineNumber":281,"sourceCode":"                // 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);\n            }\n        }\n        if (toAbort.equals(metadata.myNodeId()))\n        {\n            if (ssMode != null && StorageService.instance.operationMode() != ssMode)\n            {\n                String msg = String.format(\"Can't abort a %s operation unless it has failed\", kind);\n                logger.info(msg);\n                throw new IllegalStateException(msg);\n            }\n            StorageService.instance.clearTransientMode();\n        }\n        else if (Gossiper.instance.isAlive(metadata.directory.endpoint(toAbort)))\n        {\n            String msg = String.format(\"Can't abort a %s operation for a node %s (%s) that is UP - run abortdecommission on that instance\",\n                                       kind, toAbort, metadata.directory.endpoint(toAbort));\n            logger.info(msg);\n            throw new IllegalStateException(msg);\n        }\n        ClusterMetadataService.instance().commit(new CancelInProgressSequence(toAbort));\n    }\n}\n","sourceCodeStart":263,"sourceCodeEnd":295,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/sequences/SingleNodeSequences.java#L263-L295","documentation":"abortHelper only allows aborting a decommission/remove/move of the LOCAL node when StorageService is in the expected failed operation mode. If the operation mode does not match the expected mode for that abort kind, the operation is considered still running (or absent) and IllegalStateException is thrown. Local aborts are only meaningful for failed operations.","triggerScenarios":"Running abortdecommission/abortremove/abortmove on the node itself while StorageService.instance.operationMode() is not the expected failed mode (e.g. still NORMAL, DECOMMISSIONED already cleared, or LEAVING/moving in progress rather than failed).","commonSituations":"Operator tries to abort a decommission that is still actively running instead of waiting for it to fail; abort issued after clearTransientMode already reset the mode; wrong abort command for the operation type.","solutions":["Wait until the operation fails and the node enters the expected failed mode, then abort","If the operation is still running, cancel it with the regular operation-specific cancel/stop mechanism instead of abort","If the mode is stuck, check StorageService operation mode via nodetool and restart the node if the mode is stale"],"exampleFix":"// before\nnodetool abortdecommission   // decommission still running\n// after\n// let it fail or stop it first:\nnodetool decommissionwatch / cancel the running decommission,\nconfirm failed mode, then:\nnodetool abortdecommission","handlingStrategy":"validation","validationCode":"// only abort locally when the expected failed mode is active\nString mode = StorageService.instance.operationMode();\nif (!expectedFailedMode.equals(mode))\n    throw new IllegalStateException(\"Cannot abort in mode \" + mode);","typeGuard":null,"tryCatchPattern":"try { abortLocal(kind); }\ncatch (IllegalStateException e) {\n    if (e.getMessage().contains(\"unless it has failed\")) { /* operation still running; wait or cancel */ }\n    else throw e;\n}","preventionTips":["Wait for the operation to actually fail before aborting","Check operationMode via nodetool before aborting","Use the abort command matching the failed operation kind (abortdecommission vs abortremove vs abortmove)"],"tags":["cluster-operations","operation-mode","tcm"],"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"}