{"record":{"id":"227427abb4af077e","repo":"apache/cassandra","slug":"node-in-state-wait-for-status-to-become-normal","errorCode":null,"errorMessage":"Node in  state; wait for status to become normal","messagePattern":"Node in  state; wait for status to become normal","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/tcm/sequences/SingleNodeSequences.java","lineNumber":75,"sourceCode":"    Logger logger = LoggerFactory.getLogger(SingleNodeSequences.class);\n\n    /**\n     * Entrypoint to begin node decommission process.\n     *\n     * @param shutdownNetworking if set to true, will also shut down networking on completion\n     * @param force if set to true, will decommission the node even if this would mean there will be not enough nodes\n     *              to satisfy replication factor\n     */\n    static void decommission(boolean shutdownNetworking, boolean force)\n    {\n        if (ClusterMetadataService.instance().isMigrating() || ClusterMetadataService.state() == ClusterMetadataService.State.GOSSIP)\n            throw new IllegalStateException(\"This cluster is migrating to cluster metadata, can't decommission until that is done.\");\n\n        ClusterMetadata metadata = ClusterMetadata.current();\n\n        StorageService.Mode mode = StorageService.instance.operationMode();\n        if (!EnumSet.of(LEAVING, NORMAL, DECOMMISSION_FAILED).contains(mode))\n            throw new UnsupportedOperationException(\"Node in \" + mode + \" state; wait for status to become normal\");\n        logger.debug(\"DECOMMISSIONING\");\n\n        NodeId self = metadata.myNodeId();\n        Collection<Token> tokens = metadata.tokenMap.tokens(self);\n        ReconfigureCMS.maybeReconfigureCMS(metadata, getBroadcastAddressAndPort());\n        MultiStepOperation<?> inProgress = metadata.inProgressSequences.get(self);\n\n        if (inProgress == null)\n        {\n            logger.info(\"starting decommission with {} {}\", metadata.epoch, self);\n            // We reset transferred ranges upon starting a decommission so that we fully stream\n            // anything written since a previous attempt which may not have been persisted to a pending endpoint\n            SystemKeyspace.resetTransferredRanges();\n            logger.info(\"done resetting transferred ranges {} {}\", metadata.epoch, self);\n            ClusterMetadataService.instance().commit(new PrepareLeave(self,\n                                                                      force,\n                                                                      ClusterMetadataService.instance().placementProvider(),\n                                                                      LeaveStreams.Kind.UNBOOTSTRAP),","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/sequences/SingleNodeSequences.java#L57-L93","documentation":"decommission checks StorageService.instance.operationMode() and only permits LEAVING, NORMAL, or DECOMMISSION_FAILED. If the node is in any other mode (e.g. BOOTSTRAP, JOINING, STARTING, or mid-rebuild), it throws this UnsupportedOperationException. The message interpolates the current mode.","triggerScenarios":"Calling decommission while the node's operation mode is not NORMAL/LEAVING/DECOMMISSION_FAILED — e.g. the node is still joining, bootstrapping, or recovering from a failed decommission in another state.","commonSituations":"Operator runs decommission too soon after node start before status is NORMAL; a previous bootstrap or join is still in flight; a stuck prior operation left the node in a non-normal mode.","solutions":["Wait until `nodetool status` / logs show the node is in NORMAL state, then retry decommission.","If stuck in DECOMMISSION_FAILED, decommission is allowed — retry it to resume/finish.","If a join/bootstrap is genuinely in progress, complete or abort it first.","After a crash, restart the node so it settles into NORMAL before decommissioning."],"exampleFix":"// before\nnodetool decommission  // node still JOINING\n// after\n// guard before calling\nif (StorageService.instance.operationMode() == StorageService.Mode.NORMAL) {\n    nodetool.decommission();\n}","handlingStrategy":"validation","validationCode":"StorageService.Mode mode = StorageService.instance.operationMode();\nif (!EnumSet.of(Mode.LEAVING, Mode.NORMAL, Mode.DECOMMISSION_FAILED).contains(mode)) {\n    throw new RuntimeException(\"Node in \" + mode + \" state; decommission not allowed yet\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    decommission();\n} catch (UnsupportedOperationException e) {\n    if (e.getMessage().startsWith(\"Node in \") && e.getMessage().contains(\"wait for status\")) {\n        waitForMode(StorageService.Mode.NORMAL);\n        decommission();\n    } else throw e;\n}","preventionTips":["Check `nodetool status` / operation mode shows NORMAL before decommissioning.","Script maintenance to wait for node readiness after startup.","Handle DECOMMISSION_FAILED by simply retrying decommission.","Avoid issuing topology commands concurrently from multiple operators."],"tags":["decommission","node-state","operation-mode","topology"],"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"}