apache/cassandra · error · NotCMSException

This node is not in the CMS, can't generate a consistent…

Error message

This node is not in the CMS, can't generate a consistent log fetch response to 

What it means

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.

Solutions

  1. Re-discover current CMS membership (ClusterMetadataService.currentCMS or placement info) and send the consistent fetch to a node that is a current CMS member.
  2. If the fetcher is itself joining/rejoining, wait until it is registered or use a non-consistent fetch (consistentFetch=false) for bootstrap catch-up.
  3. Refresh stale routing/membership caches on the requesting node so requests stop targeting ex-CMS members.
  4. Retry after CMS reconfiguration completes; transient refusal during placement changes is expected.

Example fix

// caller-side: pick a CMS member for consistent fetch
InetAddressAndPort cms = ClusterMetadataService.instance().currentCMS();
if (!ClusterMetadataService.instance().isCurrentMember(peer))
    peer = cms; // before sending FetchCMSLog with consistentFetch = true
Defensive patterns

Strategy: validation

Validate before calling

if (!ClusterMetadataService.instance().isCurrentMember(target))
    target = ClusterMetadataService.instance().currentCMS(); // re-route consistent fetch to a CMS member

Try / catch

try { logState = peer.fetchLogEntries(...); } catch (NotCMSException e) { logState = fetchFromCurrentCMS(); }

Prevention

When it happens

Trigger: A peer sends FetchCMSLog with consistentFetch=true to a node for which ClusterMetadataService.instance().isCurrentMember(FBUtilities.getBroadcastAddressAndPort()) is false at FetchCMSLog.java:112.

Common situations: 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.

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/cd13cc67d7114f9e. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/tcm/FetchCMSLog.java:112

        public Handler()
        {
            this(DistributedMetadataLogKeyspace::getLogState);
        }

        public Handler(BiFunction<Epoch, Boolean, LogState> logStateSupplier)
        {
            this.logStateSupplier = logStateSupplier;
        }

        public void doVerb(Message<FetchCMSLog> message) throws IOException
        {
            FetchCMSLog request = message.payload;

            if (logger.isTraceEnabled())
                logger.trace("Received log fetch request {} from {}: start = {}, current = {}", request, message.from(), message.payload.lowerBound, ClusterMetadata.current().epoch);

            if (request.consistentFetch && !ClusterMetadataService.instance().isCurrentMember(FBUtilities.getBroadcastAddressAndPort()))
                throw new NotCMSException("This node is not in the CMS, can't generate a consistent log fetch response to " + message.from());

            // If both we and the other node believe it should be caught up with a linearizable read
            boolean consistentFetch = request.consistentFetch && !ClusterMetadataService.instance().isCurrentMember(message.from());

            LogState delta = logStateSupplier.apply(message.payload.lowerBound, consistentFetch);
            TCMMetrics.instance.cmsLogEntriesServed(message.payload.lowerBound, delta.latestEpoch());
            logger.info("Responding to {}({}) with log delta: {}", message.from(), request, delta);
            MessagingService.instance().send(message.responseWith(delta), message.from());
        }
    }
}

View on GitHub (pinned to 88fd0f6a0e)