{"record":{"id":"91bf982f6902d228","repo":"apache/cassandra","slug":"node-nodeiporid-is-in-nodestate-state-only","errorCode":null,"errorMessage":"Node ${nodeIpOrId} is in ${nodeState} state. Only a JOINED node can be set as CMS member.","messagePattern":"Node (.+?) is in (.+?) state\\. Only a JOINED node can be set as CMS member\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/tools/CMSOfflineTool.java","lineNumber":439,"sourceCode":"        @Option(names = { \"-o\", \"--output-file\" },\n        description = \"Output file path for storing the updated Cluster Metadata.\")\n        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            metadata = resetCMS(metadata, nodeId);\n            writeMetadata(output, metadata, outputFilePath);\n        }\n\n        ClusterMetadata resetCMS(ClusterMetadata metadata, NodeId nodeId)\n        {\n            NodeState nodeState = metadata.directory.peerState(nodeId);\n            if (nodeState != NodeState.JOINED)\n            {\n                throw new IllegalArgumentException(\"Node \" + nodeIdentifierOption.getNodeIpOrId() + \" is in \" +\n                                                   nodeState + \" state. Only a JOINED node can be set as CMS member.\");\n            }\n            InetAddressAndPort endpoint = metadata.directory.getNodeAddresses(nodeId).broadcastAddress;\n            CMSMembership cms = metadata.cmsMembership;\n            ClusterMetadata.Transformer transformer = metadata.transformer();\n            for (NodeId id : cms.fullMembers())\n                transformer = transformer.leaveCMS(id);\n            for (NodeId id : cms.joiningMembers())\n                transformer = transformer.cancelJoiningCMS(id);\n\n            transformer = transformer.startJoiningCMS(nodeId).finishJoiningCMS(nodeId);\n            return transformer.build().metadata;\n        }\n    }\n\n    /**\n     * Moves a node to a new token. Only supports single-token nodes.\n     * If a MOVE sequence is already in progress for the node, it is completed rather than started fresh;","sourceCodeStart":421,"sourceCodeEnd":457,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tools/CMSOfflineTool.java#L421-L457","documentation":"resetCMS rebuilds CMS membership to a single node, but only a node in NodeState.JOINED may become a CMS member. If metadata.directory.peerState(nodeId) is anything else (REGISTERED, LEAVING, LEFT, etc.), this IllegalArgumentException is thrown.","triggerScenarios":"Calling resetCMS from `execute` when the selected node's peer state is not JOINED — e.g. the node is still registering, has been decommissioned, or was never fully joined.","commonSituations":"Operator picks a replacement/new node by ID or IP that finished bootstrap metadata but not the JOINED transition; node was removed previously and its directory entry remains in a non-JOINED state.","solutions":["Choose a node whose peer state is JOINED as the new CMS member.","If the intended node is mid-join, let the join complete (or abort it) so its state becomes JOINED, then re-run resetCMS.","Verify with the directory/peer state which nodes are JOINED before invoking the reset."],"exampleFix":"// before\nbin/cms reset-cms -id 3   // node 3 is REGISTERED\n// after\nbin/cms reset-cms -id 2   // node 2 is JOINED","handlingStrategy":"validation","validationCode":"NodeId nodeId = /* resolved */;\nif (meta.directory.peerState(nodeId) != NodeState.JOINED)\n    throw new IllegalStateException(\"Node \" + nodeId + \" is \" + meta.directory.peerState(nodeId) + \", not JOINED\");","typeGuard":null,"tryCatchPattern":"try { tool.resetCms(nodeId); } catch (IllegalArgumentException e) { if (e.getMessage().contains(\"Only a JOINED node\")) { pickJoinedNodeAndRetry(); } else throw e; }","preventionTips":["Check peerState of the candidate node before resetting CMS membership.","Only select fully-joined, stable nodes as CMS members.","Handle half-joined nodes via abortbootstrap/completion before using them for CMS."],"tags":["node-state","cms-membership","reset","cluster-metadata"],"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"}