{"record":{"id":"2facc6f14b7557a0","repo":"apache/cassandra","slug":"node-s-is-not-a-cms-member-in-epoch-s-members","errorCode":null,"errorMessage":"Node %s is not a CMS member in epoch %s; members=%s","messagePattern":"Node (.+?) is not a CMS member in epoch (.+?); members=(.+?)","errorType":"exception","errorClass":"NotCMSException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/tcm/AbstractLocalProcessor.java","lineNumber":72,"sourceCode":"     * the time when this method returns.\n     */\n    @Override\n    public final Commit.Result commit(Entry.Id entryId, Transformation transform, final Epoch lastKnown, Retry retryPolicy)\n    {\n        String transformStr = transform.toString(); // convert once as idempotent and used in multiple logs\n        logger.debug(\"Starting local commit of {} with policy {}\", transformStr, retryPolicy);\n        long commitStart = nanoTime();\n        while (!retryPolicy.hasExpired())\n        {\n            ClusterMetadata previous = log.waitForHighestConsecutive();\n            if (!acceptCommit(previous))\n            {\n                String msg = String.format(\"Node %s is not a CMS member in epoch %s; members=%s\",\n                                           FBUtilities.getBroadcastAddressAndPort(),\n                                           previous.epoch.getEpoch(),\n                                           previous.fullCMSMembers());\n                logger.warn(msg);\n                throw new NotCMSException(msg);\n            }\n\n            Transformation.Result result;\n            if (!transform.eligibleToCommit(previous))\n            {\n                result = new Transformation.Rejected(INVALID, \"Transformation rejected, can't commit \" + transformStr +\n                                                              \" it not supported with cluster common serialization version \" + previous.directory.commonSerializationVersion +\n                                                              \" and min/max serialization versions \" + previous.directory.clusterMinVersion + \"/\" + previous.directory.clusterMaxVersion);\n            }\n            else\n            {\n                result = executeStrictly(previous, transform);\n            }\n            Version previousVersion = previous.directory.commonSerializationVersion;\n            if (result.isSuccess())\n            {\n                Version newVersion = result.success().metadata.directory.commonSerializationVersion;\n                if (previousVersion.isEqualOrBefore(Version.V9) &&","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/AbstractLocalProcessor.java#L54-L90","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before: committing on non-CMS node\nNodeOperations.commit(transform); // NotCMSException\n// after: target a CMS member\nList<InetSocketAddress> members = clusterMetadata().fullCMSMembers();\nrunOnNode(members.get(0), () -> NodeOperations.commit(transform));","handlingStrategy":"try-catch","validationCode":"Set<InetSocketAddress> members = clusterMetadata().previous.fullCMSMembers();\nif (!members.contains(FBUtilities.getBroadcastAddressAndPort()))\n    throw new NotCMSException(\"this node is not a CMS member; route commit to \" + members);","typeGuard":null,"tryCatchPattern":"try { processor.commit(transform); }\ncatch (NotCMSException e) {\n    logger.warn(\"not CMS member: {}\", e.getMessage());\n    routeCommitToCmsMember(transform); // forward to an actual CMS member\n}","preventionTips":["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"],"tags":["tcm","cms","cluster-metadata"],"backgroundTag":"permission-denied","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}