apache/cassandra · error · IllegalStateException

Can't apply a ClusterMetadata from gossip when CMSState is…

Error message

Can't apply a ClusterMetadata from gossip when CMSState is not GOSSIP: 

What it means

applyFromGossip requires the ClusterMetadataService to be in the GOSSIP state (the pre-migration mode). If the service has already transitioned to TCM/CMS state, applying metadata from gossip is rejected with IllegalStateException including the current state, since gossip is no longer the authoritative source.

Solutions

  1. Check ClusterMetadataService.instance().state() == GOSSIP before calling applyFromGossip.
  2. Complete the cluster migration so gossip peers stop sending metadata updates to migrated nodes.
  3. If this happens during a rolling upgrade, ensure all nodes migrate in the documented order and drop stale gossip traffic.
  4. In test tooling, reset the CMS state to GOSSIP before invoking gossip-apply paths.

Example fix

// before
service.applyFromGossip(expected, updated);
// after
if (ClusterMetadataService.instance().state() == CMSState.GOSSIP)
    service.applyFromGossip(expected, updated);
else
    logger.warn("Ignoring gossip metadata while state is {}", ClusterMetadataService.instance().state());
Defensive patterns

Strategy: validation

Validate before calling

if (ClusterMetadataService.instance().state() != CMSState.GOSSIP) return false;

Type guard

boolean canApplyFromGossip = ClusterMetadataService.instance().state() == CMSState.GOSSIP;

Try / catch

try { service.applyFromGossip(expected, updated); } catch (IllegalStateException e) { logger.warn("Cannot apply from gossip in state {}: {}", ClusterMetadataService.instance().state(), e.getMessage()); }

Prevention

When it happens

Trigger: Calling applyFromGossip(expected, updated) when ClusterMetadataService.state() != CMSState.GOSSIP — e.g. after the node completed the gossip-to-TCM migration and its state moved to TCM/ELECTION.

Common situations: Gossip messages still arriving after migration completed; mixed-version cluster where an old node pushes metadata to a migrated node; calling internal migration APIs out of order during testing or custom tooling.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/tcm/ClusterMetadataService.java:541

        try
        {
            reconfigureCMS(ReplicationParams.meta(metadata));
        }
        catch (Throwable t)
        {
            JVMStabilityInspector.inspectThrowable(t);
            logger.warn("Could not reconfigure CMS, operator should run `nodetool cms reconfigure` to make sure CMS placement is correct", t);
        }
    }

    public boolean applyFromGossip(ClusterMetadata expected, ClusterMetadata updated)
    {
        logger.debug("Applying from gossip, current={} new={}", expected, updated);
        if (!expected.epoch.isBefore(Epoch.EMPTY))
            throw new IllegalStateException("Can't apply a ClusterMetadata from gossip with epoch " + expected.epoch);
        if (state() != GOSSIP)
            throw new IllegalStateException("Can't apply a ClusterMetadata from gossip when CMSState is not GOSSIP: " + state());

        return log.unsafeSetCommittedFromGossip(expected, updated);
    }

    public void setFromGossip(ClusterMetadata fromGossip)
    {
        logger.debug("Setting from gossip, new={}", fromGossip);
        if (state() != GOSSIP)
            throw new IllegalStateException("Can't apply a ClusterMetadata from gossip when CMSState is not GOSSIP: " + state());
        log.unsafeSetCommittedFromGossip(fromGossip);
    }

    public void forceSnapshot(ClusterMetadata snapshot)
    {
        commit(new ForceSnapshot(snapshot));
    }

    public void revertToEpoch(Epoch epoch)

View on GitHub (pinned to 88fd0f6a0e)