apache/cassandra · error · IllegalArgumentException
Node ${nodeIpOrId} is in ${nodeState} state. Only a JOINED n
Error message
Node ${nodeIpOrId} is in ${nodeState} state. Only a JOINED node can be set as CMS member. What it means
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.
Source
Thrown at src/java/org/apache/cassandra/tools/CMSOfflineTool.java:439
@Option(names = { "-o", "--output-file" },
description = "Output file path for storing the updated Cluster Metadata.")
private String outputFilePath;
@Override
protected void execute(Output output) throws IOException
{
ClusterMetadata metadata = parseClusterMetadata();
NodeId nodeId = nodeIdentifierOption.getNodeId(metadata);
metadata = resetCMS(metadata, nodeId);
writeMetadata(output, metadata, outputFilePath);
}
ClusterMetadata resetCMS(ClusterMetadata metadata, NodeId nodeId)
{
NodeState nodeState = metadata.directory.peerState(nodeId);
if (nodeState != NodeState.JOINED)
{
throw new IllegalArgumentException("Node " + nodeIdentifierOption.getNodeIpOrId() + " is in " +
nodeState + " state. Only a JOINED node can be set as CMS member.");
}
InetAddressAndPort endpoint = metadata.directory.getNodeAddresses(nodeId).broadcastAddress;
CMSMembership cms = metadata.cmsMembership;
ClusterMetadata.Transformer transformer = metadata.transformer();
for (NodeId id : cms.fullMembers())
transformer = transformer.leaveCMS(id);
for (NodeId id : cms.joiningMembers())
transformer = transformer.cancelJoiningCMS(id);
transformer = transformer.startJoiningCMS(nodeId).finishJoiningCMS(nodeId);
return transformer.build().metadata;
}
}
/**
* Moves a node to a new token. Only supports single-token nodes.
* If a MOVE sequence is already in progress for the node, it is completed rather than started fresh;View on GitHub (pinned to 88fd0f6a0e)
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.
Example fix
// before bin/cms reset-cms -id 3 // node 3 is REGISTERED // after bin/cms reset-cms -id 2 // node 2 is JOINED
Defensive patterns
Strategy: validation
Validate before calling
NodeId nodeId = /* resolved */;
if (meta.directory.peerState(nodeId) != NodeState.JOINED)
throw new IllegalStateException("Node " + nodeId + " is " + meta.directory.peerState(nodeId) + ", not JOINED"); Try / catch
try { tool.resetCms(nodeId); } catch (IllegalArgumentException e) { if (e.getMessage().contains("Only a JOINED node")) { pickJoinedNodeAndRetry(); } else throw e; } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
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
- Initial CMS node needs to be fully joined, not: %s
- Could not remove node ${nodeIpOrId} from CMS.
- Node ${nodeIpOrId} is already in JOINED state.
- CMS Membership differ: {} != {}
- Unable to stop gossip because the node is not in the normal
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/91bf982f6902d228.
Report an issue: GitHub.