apache/cassandra · error · NotCMSException

Not currently a member of the CMS, can't commit

Error message

Not currently a member of the CMS, can't commit

What it means

Commit.doVerb handles incoming commit requests on a CMS member. Before processing, checkCMSState() verifies the node is actually part of the CMS. If the node's CMS state is REMOTE — meaning CMS membership lives elsewhere — it throws NotCMSException with this message instead of attempting a Paxos commit it is not entitled to make.

Solutions

  1. Refresh CMS placement info: run nodetool cms show / awaitClusterMetadata to learn the current CMS members and route commits there
  2. Let ClusterMetadataService re-discover the CMS (the caller typically retries against the new CMS members after this exception)
  3. Ensure the messaging/cache layer isn't pinning stale CMS addresses — restart the misrouted node or clear cached placements if needed
  4. During CMS migration, pause topology operations until the placement change is fully enacted

Example fix

// before: committing without checking local CMS membership
ClusterMetadataService.instance.commit(transform, onSuccess, onFailure);
// after: only commit when this node can act as CMS, otherwise refresh placement and retry
if (ClusterMetadataService.instance.getState().equals(CMSState.REMOTE))
{
    // ask the actual CMS members instead, or await placement refresh
    ClusterMetadataService.instance.refreshCMSMembership();
    throw new NotCMSException("Re-routed: this node is not a CMS member");
}
ClusterMetadataService.instance.commit(transform, onSuccess, onFailure);
Defensive patterns

Strategy: retry

Validate before calling

CMSState state = ClusterMetadataService.instance.getState();
if (state == CMSState.REMOTE)
    throw new NotCMSException("Refusing to commit: this node is not a CMS member");
if (state == CMSState.GOSSIP)
    throw new IllegalStateException("Node in gossip mode; cannot commit");

Type guard

boolean canCommitLocally = () -> {
    CMSState s = ClusterMetadataService.instance.getState();
    return s == CMSState.LOCAL || s == CMSState.RESET;
};

Try / catch

try
{
    commit(entryId, transform, lastKnown, retry);
}
catch (NotCMSException e)
{
    // re-resolve current CMS members and retry the commit against them
    ClusterMetadataService.instance.refreshCMSMembership();
    retryAgainstCurrentCMS();
}

Prevention

When it happens

Trigger: A commit request arrives at a node that previously was (or was thought to be) a CMS member but whose CMS state is now REMOTE, e.g. after CMS re-placement/migration moved CMS to other nodes and stale routing still sends commit verbs here.

Common situations: In-flight commit requests routed to a node right after CMS membership changed; clients or caches holding stale CMS addresses; rolling upgrades during a CMS placement change.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/tcm/Commit.java:420

            if (result.isSuccess())
            {
                Result.Success success = result.success();
                replicator.send(success, message.from());
                logger.info("Responding with full result {} to sender {}", result, message.from());
            }

            messagingService.accept(message.responseWith(result), message.from());
        }

        private void checkCMSState()
        {
            switch (cmsStateSupplier.get())
            {
                case RESET:
                case LOCAL:
                    break;
                case REMOTE:
                    throw new NotCMSException("Not currently a member of the CMS, can't commit");
                case GOSSIP:
                    String msg = "Tried to commit when in gossip mode";
                    logger.error(msg);
                    throw new IllegalStateException(msg);
                default:
                    throw new IllegalStateException("Illegal state: " + cmsStateSupplier.get());
            }
        }
    }

    public interface Replicator
    {
        Replicator NO_OP = (a,b) -> {};
        void send(Result result, InetAddressAndPort source);
    }

    public static class DefaultReplicator implements Replicator
    {

View on GitHub (pinned to 88fd0f6a0e)