apache/cassandra · warning · IllegalStateException
%s is already joining the CMS
Error message
%s is already joining the CMS
What it means
CMSMembership is an immutable TCM transformation result representing CMS membership state. startJoining(id) throws IllegalStateException when the requested node id is already in the joiningMembers set — the transformation to mark it as joining would create a duplicate, so it is rejected.
Source
Thrown at src/java/org/apache/cassandra/tcm/CMSMembership.java:140
public Epoch lastModified()
{
return lastModified;
}
public Set<NodeId> joiningMembers()
{
return joiningMembers;
}
public Set<NodeId> fullMembers()
{
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)
{View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Check current CMS state (joining members) before retrying; if the node is already joining, wait for the join to finish instead of re-issuing
- Use idempotent join handling: catch IllegalStateException and treat 'already joining' as success in the orchestration
- Cancel the stale joining entry (cancelJoining) if the join attempt is truly dead, then start joining again
- De-duplicate concurrent join automation with a single coordination point/lock
Example fix
// before
Membership members = cms.join(nodeId); // may throw if already joining
// after
try { members = cms.join(nodeId); }
catch (IllegalStateException e) {
if (e.getMessage().contains("already joining")) return; // idempotent
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
if (membership.joiningMembers().contains(nodeId)) skipJoin(nodeId); // already in progress
Try / catch
try { membership = cms.startJoining(nodeId); }
catch (IllegalStateException e) {
if (e.getMessage().endsWith("is already joining the CMS")) return; // idempotent no-op
throw e;
} Prevention
- Check joiningMembers before issuing a join
- Make join automation idempotent
- Serialize join requests for a node through a single coordinator
When it happens
Trigger: A CMS join/StartJoining transformation is applied (via a CMS processor commit) for a NodeId that is already tracked as joining; typically a retried join request or two concurrent join attempts for the same node.
Common situations: Retrying a failed/timeout join command without checking its outcome; operator running the CMS-join procedure twice; automation races issuing join for the same node from two places.
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 has already fully joined the CMS
- %s is not currently joining the CMS
- has already fully joined 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/f6ef6bbf065a59fa.
Report an issue: GitHub.