{"record":{"id":"3960788bd5b03c04","repo":"apache/cassandra","slug":"has-already-fully-joined-the-cms","errorCode":null,"errorMessage":" 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":152,"sourceCode":"        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\");\n        if (fullMembers.contains(id))\n            throw new IllegalStateException(id + \" has already fully joined the CMS\");\n\n        return new CMSMembership(lastModified, fullMembers.with(id), joiningMembers.without(id));\n    }\n\n    public CMSMembership leave(NodeId id)\n    {\n        if (joiningMembers.contains(id))\n            throw new IllegalStateException(id + \" is currently joining the CMS, \");","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/CMSMembership.java#L134-L170","documentation":"Within CMSMembership.cancelJoining, after confirming the node is in joiningMembers, it also checks fullMembers; if the node has already fully joined, IllegalStateException with 'has already fully joined the CMS' is thrown — cancelling is invalid because the join already completed.","triggerScenarios":"A cancelJoining transformation racing with finishJoining: the cancel was validated against a stale snapshot in which the node was joining, but by the time it applies, the node already appears in fullMembers; or a timeout handler cancelling a join that completed successfully.","commonSituations":"Join timeout fires just as the join finishes; two failure handlers acting on the same join; orchestration reading an outdated epoch snapshot before issuing the cancel.","solutions":["Re-read the latest metadata and check fullMembers before issuing cancelJoining; treat an already-full member as joined (success)","Restructure timeout handlers to always re-fetch current CMS state instead of acting on captured snapshots","Coordinate join lifecycle (start/cancel/finish) through one serialized owner to remove the race","If the node joined successfully, no action is needed — update automation state and stop the cancel path"],"exampleFix":"// before\nmembership = cms.cancelJoining(nodeId);\n// after\nif (cms.fullMembers().contains(nodeId)) return; // join completed; nothing to cancel\nif (cms.joiningMembers().contains(nodeId))\n    membership = cms.cancelJoining(nodeId);","handlingStrategy":"validation","validationCode":"if (membership.fullMembers().contains(nodeId)) return; // join already completed; do not cancel","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Re-read latest metadata before issuing cancelJoining to avoid stale-snapshot races","Have timeout handlers check fullMembers first","Serialize start/cancel/finish join operations to eliminate interleaving"],"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"}