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

  1. 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)
  2. Reload/re-read the latest cluster metadata epoch so the node's view of CMS membership is current before committing
  3. If CMS membership is wrong, use the TCM/CMS reconfiguration tooling (e.g. nodetool cms admit/reconfigure) to fix membership
  4. 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

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


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/2facc6f14b7557a0. Report an issue: GitHub.