apache/cassandra · error · NotCMSException
Node %s is not a CMS member in epoch %s; members=%s
Error message
Node %s is not a CMS member in epoch %s; members=%s
What it means
AbstractLocalProcessor.commit executes a TCM (Transaction Cluster Metadata) transformation locally and first verifies the committing node is a member of the CMS (Cluster Metadata Service) for the previous epoch. If not, it logs a warning and throws NotCMSException: only CMS members may commit transformations against cluster metadata in that epoch.
Source
Thrown at src/java/org/apache/cassandra/tcm/AbstractLocalProcessor.java:72
* the time when this method returns.
*/
@Override
public final Commit.Result commit(Entry.Id entryId, Transformation transform, final Epoch lastKnown, Retry retryPolicy)
{
String transformStr = transform.toString(); // convert once as idempotent and used in multiple logs
logger.debug("Starting local commit of {} with policy {}", transformStr, retryPolicy);
long commitStart = nanoTime();
while (!retryPolicy.hasExpired())
{
ClusterMetadata previous = log.waitForHighestConsecutive();
if (!acceptCommit(previous))
{
String msg = String.format("Node %s is not a CMS member in epoch %s; members=%s",
FBUtilities.getBroadcastAddressAndPort(),
previous.epoch.getEpoch(),
previous.fullCMSMembers());
logger.warn(msg);
throw new NotCMSException(msg);
}
Transformation.Result result;
if (!transform.eligibleToCommit(previous))
{
result = new Transformation.Rejected(INVALID, "Transformation rejected, can't commit " + transformStr +
" it not supported with cluster common serialization version " + previous.directory.commonSerializationVersion +
" and min/max serialization versions " + previous.directory.clusterMinVersion + "/" + previous.directory.clusterMaxVersion);
}
else
{
result = executeStrictly(previous, transform);
}
Version previousVersion = previous.directory.commonSerializationVersion;
if (result.isSuccess())
{
Version newVersion = result.success().metadata.directory.commonSerializationVersion;
if (previousVersion.isEqualOrBefore(Version.V9) &&View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Ensure the operation is run on / routed to a CMS member node (query cms membership via nodetool cms or JMX and target a current member)
- Reload/re-read the latest cluster metadata epoch so the node's view of CMS membership is current before committing
- If CMS membership is wrong, use the TCM/CMS reconfiguration tooling (e.g. nodetool cms admit/reconfigure) to fix membership
- Check for epoch lag/partitioning between the node and CMS; resolve network issues and restart the failed operation
Example fix
// before: committing on non-CMS node NodeOperations.commit(transform); // NotCMSException // after: target a CMS member List<InetSocketAddress> members = clusterMetadata().fullCMSMembers(); runOnNode(members.get(0), () -> NodeOperations.commit(transform));
Defensive patterns
Strategy: try-catch
Validate before calling
Set<InetSocketAddress> members = clusterMetadata().previous.fullCMSMembers();
if (!members.contains(FBUtilities.getBroadcastAddressAndPort()))
throw new NotCMSException("this node is not a CMS member; route commit to " + members); Try / catch
try { processor.commit(transform); }
catch (NotCMSException e) {
logger.warn("not CMS member: {}", e.getMessage());
routeCommitToCmsMember(transform); // forward to an actual CMS member
} Prevention
- Only issue TCM transformations on CMS member nodes
- Refresh cluster metadata (latest epoch) before committing transforms
- Monitor CMS membership changes; re-target operations after reconfiguration
When it happens
Trigger: A node calls commit() on a processor/transform (e.g. during metadata changes or join operations) while its address is absent from previous.fullCMSMembers() for the current epoch — e.g. after a CMS membership change the node has not caught up on, or a non-CMS node attempting local commits.
Common situations: Node recently removed from CMS or joined before CMS membership propagated; epoch divergence where the node reads a stale/mismatched epoch; operational mistakes running transform-committing commands on a non-CMS node; replica/CMS reconfiguration mid-operation.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- %s is already joining the CMS
- %s has already fully joined the CMS
- %s is not currently joining the CMS
- has already fully joined the CMS
- Couldn't commit the transformation. Is the node shutting dow
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/2facc6f14b7557a0.
Report an issue: GitHub.