apache/cassandra · warning · IllegalStateException
has already fully joined the CMS
Error message
has already fully joined the CMS
What it means
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.
Source
Thrown at src/java/org/apache/cassandra/tcm/CMSMembership.java:152
return fullMembers;
}
public CMSMembership startJoining(NodeId id)
{
if (joiningMembers.contains(id))
throw new IllegalStateException(id + " is already joining the CMS");
if (fullMembers.contains(id))
throw new IllegalStateException(id + " has already fully joined the CMS");
return new CMSMembership(lastModified, fullMembers, joiningMembers.with(id));
}
public CMSMembership cancelJoining(NodeId id)
{
if (!joiningMembers.contains(id))
throw new IllegalStateException(id + " is not currently joining the CMS");
if (fullMembers.contains(id))
throw new IllegalStateException(id + " has already fully joined the CMS");
return new CMSMembership(lastModified, fullMembers, joiningMembers.without(id));
}
public CMSMembership finishJoining(NodeId id)
{
if (!joiningMembers.contains(id))
throw new IllegalStateException(id + " is not currently joining the CMS");
if (fullMembers.contains(id))
throw new IllegalStateException(id + " has already fully joined the CMS");
return new CMSMembership(lastModified, fullMembers.with(id), joiningMembers.without(id));
}
public CMSMembership leave(NodeId id)
{
if (joiningMembers.contains(id))
throw new IllegalStateException(id + " is currently joining the CMS, ");View on GitHub (pinned to 88fd0f6a0e)
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
Example fix
// before
membership = cms.cancelJoining(nodeId);
// after
if (cms.fullMembers().contains(nodeId)) return; // join completed; nothing to cancel
if (cms.joiningMembers().contains(nodeId))
membership = cms.cancelJoining(nodeId); Defensive patterns
Strategy: validation
Validate before calling
if (membership.fullMembers().contains(nodeId)) return; // join already completed; do not cancel
Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- %s is already joining the CMS
- %s has already fully joined the CMS
- %s is not currently joining the CMS
- Node %s is not a CMS member in epoch %s; members=%s
- Could not catch up to epoch %s even after fetching log from
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/3960788bd5b03c04.
Report an issue: GitHub.