{"record":{"id":"6b6eca81d05f1cf9","repo":"apache/cassandra","slug":"s-has-already-fully-joined-the-cms","errorCode":null,"errorMessage":"%s has already fully joined the CMS","messagePattern":"(.+?) has already fully joined the CMS","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"warning","filePath":"src/java/org/apache/cassandra/tcm/CMSMembership.java","lineNumber":142,"sourceCode":"        return lastModified;\n    }\n\n    public Set<NodeId> joiningMembers()\n    {\n        return joiningMembers;\n    }\n\n    public Set<NodeId> fullMembers()\n    {\n        return fullMembers;\n    }\n\n    public CMSMembership startJoining(NodeId id)\n    {\n        if (joiningMembers.contains(id))\n            throw new IllegalStateException(id + \" is already joining the CMS\");\n        if (fullMembers.contains(id))\n            throw new IllegalStateException(id + \" has already fully joined the CMS\");\n\n        return new CMSMembership(lastModified, fullMembers, joiningMembers.with(id));\n    }\n\n    public CMSMembership cancelJoining(NodeId id)\n    {\n        if (!joiningMembers.contains(id))\n            throw new IllegalStateException(id + \" is not currently joining the CMS\");\n        if (fullMembers.contains(id))\n            throw new IllegalStateException(id + \" has already fully joined the CMS\");\n\n        return new CMSMembership(lastModified, fullMembers, joiningMembers.without(id));\n    }\n\n    public CMSMembership finishJoining(NodeId id)\n    {\n        if (!joiningMembers.contains(id))\n            throw new IllegalStateException(id + \" is not currently joining the CMS\");","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/CMSMembership.java#L124-L160","documentation":"In CMSMembership.startJoining, after checking the joining set, it verifies the node is not already in fullMembers; if it is, IllegalStateException is thrown because the node has already fully joined the CMS and starting a join for it is meaningless and would corrupt membership state.","triggerScenarios":"Applying a startJoining transformation for a NodeId present in fullMembers — a join request replayed after successful completion, or an operator/automation re-running the join step after the node already joined.","commonSituations":"Retry logic that does not check whether the previous join succeeded; re-running bootstrap/CMS-join tooling on an already-joined node; stale orchestration state following an ambiguous command result.","solutions":["Query current CMS membership first; if the node already has full membership, skip the join step entirely","Make the join orchestration idempotent: treat 'already fully joined' as a no-op success","Update stale automation state to reflect the node's completed join before issuing further CMS operations","Only cancel/rejoin if you genuinely intend to remove and re-add the node, using cancelJoining/finishJoining transitions in the correct order"],"exampleFix":"// before\nmembership = cms.startJoining(nodeId);\n// after\nif (!cms.fullMembers().contains(nodeId))\n    membership = cms.startJoining(nodeId);","handlingStrategy":"validation","validationCode":"if (membership.fullMembers().contains(nodeId)) return; // already joined; skip startJoining","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always read current CMS membership from the latest epoch before joining","Treat completed joins as success in retry logic","Update orchestration state after join completion to avoid replays"],"tags":["tcm","cms","join"],"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"}