{"record":{"id":"8021a40d33b4a32d","repo":"apache/cassandra","slug":"can-t-resume-a-move-operation-unless-it-has-failed","errorCode":null,"errorMessage":"Can't resume a move operation unless it has failed","messagePattern":"Can't resume a move 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":234,"sourceCode":"        ClusterMetadata metadata = ClusterMetadata.current();\n        NodeId self = metadata.myNodeId();\n        MultiStepOperation<?> sequence = metadata.inProgressSequences.get(self);\n        if (sequence == null || sequence.kind() != MultiStepOperation.Kind.MOVE)\n        {\n            String msg = \"No move operation in progress, can't resume\";\n            logger.info(msg);\n            if (StorageService.instance.operationMode() == MOVE_FAILED)\n            {\n                // there is no ongoing move to resume, but operation mode thinks there is\n                StorageService.instance.clearTransientMode();\n            }\n            throw new IllegalStateException(msg);\n        }\n        if (StorageService.instance.operationMode() != MOVE_FAILED)\n        {\n            String msg = \"Can't resume a move operation unless it has failed\";\n            logger.info(msg);\n            throw new IllegalStateException(msg);\n        }\n        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    {","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/sequences/SingleNodeSequences.java#L216-L252","documentation":"resumeMove only resumes moves that FAILED: StorageService.operationMode() must be MOVE_FAILED. Otherwise it throws IllegalStateException 'Can't resume a move operation unless it has failed', preventing resuming an operation that is healthy or in another mode.","triggerScenarios":"Running `nodetool resumemove` while a MOVE sequence is in progress but the node's operation mode is not MOVE_FAILED (e.g. NORMAL, MOVE in progress, or LEAVING).","commonSituations":"Operators resuming a move that is still running (not failed); leftover transient mode cleared by a prior command; issuing resume after a manual mode change.","solutions":["Let the in-progress move finish on its own; resume is only for failed moves.","If the move is stuck but not marked failed, abort it (`nodetool abortmove`) and start a new move.","Check `nodetool netstats` / logs to see whether streaming for the move is still active before resuming."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (StorageService.instance.operationMode() != StorageService.Mode.MOVE_FAILED)\n    return; // only failed moves can be resumed","typeGuard":"boolean canResumeMove() { return StorageService.instance.operationMode() == StorageService.Mode.MOVE_FAILED; }","tryCatchPattern":"try { resumeMove(); }\ncatch (IllegalStateException e) { if (e.getMessage().contains(\"unless it has failed\")) { waitOrAbort(); } else throw e; }","preventionTips":["Only invoke resumemove after the move actually failed (MOVE_FAILED mode)","Monitor netstats to avoid aborting still-streaming moves","Prefer abort+fresh move over resume when state is unclear"],"tags":["cassandra","move","resume","operation-mode"],"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"}