{"record":{"id":"cd13cc67d7114f9e","repo":"apache/cassandra","slug":"this-node-is-not-in-the-cms-can-t-generate-a-cons","errorCode":null,"errorMessage":"This node is not in the CMS, can't generate a consistent log fetch response to ","messagePattern":"This node is not in the CMS, can't generate a consistent log fetch response to ","errorType":"exception","errorClass":"NotCMSException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/tcm/FetchCMSLog.java","lineNumber":112,"sourceCode":"        public Handler()\n        {\n            this(DistributedMetadataLogKeyspace::getLogState);\n        }\n\n        public Handler(BiFunction<Epoch, Boolean, LogState> logStateSupplier)\n        {\n            this.logStateSupplier = logStateSupplier;\n        }\n\n        public void doVerb(Message<FetchCMSLog> message) throws IOException\n        {\n            FetchCMSLog request = message.payload;\n\n            if (logger.isTraceEnabled())\n                logger.trace(\"Received log fetch request {} from {}: start = {}, current = {}\", request, message.from(), message.payload.lowerBound, ClusterMetadata.current().epoch);\n\n            if (request.consistentFetch && !ClusterMetadataService.instance().isCurrentMember(FBUtilities.getBroadcastAddressAndPort()))\n                throw new NotCMSException(\"This node is not in the CMS, can't generate a consistent log fetch response to \" + message.from());\n\n            // If both we and the other node believe it should be caught up with a linearizable read\n            boolean consistentFetch = request.consistentFetch && !ClusterMetadataService.instance().isCurrentMember(message.from());\n\n            LogState delta = logStateSupplier.apply(message.payload.lowerBound, consistentFetch);\n            TCMMetrics.instance.cmsLogEntriesServed(message.payload.lowerBound, delta.latestEpoch());\n            logger.info(\"Responding to {}({}) with log delta: {}\", message.from(), request, delta);\n            MessagingService.instance().send(message.responseWith(delta), message.from());\n        }\n    }\n}\n","sourceCodeStart":94,"sourceCodeEnd":124,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/FetchCMSLog.java#L94-L124","documentation":"FetchCMSLog.doVerb handles requests for the cluster metadata change log. When the request sets consistentFetch, the responder must be a current CMS member to produce a linearizable (consistent) log state; otherwise it throws NotCMSException. The message includes the requesting peer address. Consistent fetches require the CMS's authoritative view, so a non-member node must refuse.","triggerScenarios":"A peer sends FetchCMSLog with consistentFetch=true to a node for which ClusterMetadataService.instance().isCurrentMember(FBUtilities.getBroadcastAddressAndPort()) is false at FetchCMSLog.java:112.","commonSituations":"Client/peer pinned its CMS discovery to a node that was later removed from the CMS placement (e.g. after reconfiguration or restart); mixed-version or membership-change races where routing tables are stale; nodes catching up via a peer that is no longer in the CMS.","solutions":["Re-discover current CMS membership (ClusterMetadataService.currentCMS or placement info) and send the consistent fetch to a node that is a current CMS member.","If the fetcher is itself joining/rejoining, wait until it is registered or use a non-consistent fetch (consistentFetch=false) for bootstrap catch-up.","Refresh stale routing/membership caches on the requesting node so requests stop targeting ex-CMS members.","Retry after CMS reconfiguration completes; transient refusal during placement changes is expected."],"exampleFix":"// caller-side: pick a CMS member for consistent fetch\nInetAddressAndPort cms = ClusterMetadataService.instance().currentCMS();\nif (!ClusterMetadataService.instance().isCurrentMember(peer))\n    peer = cms; // before sending FetchCMSLog with consistentFetch = true","handlingStrategy":"validation","validationCode":"if (!ClusterMetadataService.instance().isCurrentMember(target))\n    target = ClusterMetadataService.instance().currentCMS(); // re-route consistent fetch to a CMS member","typeGuard":null,"tryCatchPattern":"try { logState = peer.fetchLogEntries(...); } catch (NotCMSException e) { logState = fetchFromCurrentCMS(); }","preventionTips":["Resolve current CMS membership dynamically instead of caching peer addresses","Re-route consistent fetches to ClusterMetadataService.currentCMS()","Use non-consistent fetches for bootstrap catch-up from non-CMS peers"],"tags":["tcm","not-cms","metadata-fetch","consistency"],"backgroundTag":"permission-denied","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}