apache/cassandra · error · IllegalStateException

Can't upgrade from gossip since CMS is already initialized

Error message

Can't upgrade from gossip since CMS is already initialized

What it means

upgradeFromGossip only makes sense when the cluster is still running in gossip mode with an uninitialized CMS. If the CMS/election is already initialized (a CMS has been placed and epochs advanced past EMPTY), the method refuses with IllegalStateException, because migrating from gossip again would overwrite or conflict with the established TCM state.

Source

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

        }

        if (existingMembers.isEmpty())
        {
            logger.info("First CMS node");
            Set<InetAddressAndPort> candidates = metadata
                                                 .directory
                                                 .allJoinedEndpoints()
                                                 .stream()
                                                 .filter(ep -> !FBUtilities.getBroadcastAddressAndPort().equals(ep) &&
                                                               !ignored.contains(ep))
                                                 .collect(toImmutableSet());

            Election.instance.nominateSelf(candidates, ignored, metadata, true);
            ClusterMetadataService.instance().triggerSnapshot();
        }
        else
        {
            throw new IllegalStateException("Can't upgrade from gossip since CMS is already initialized");
        }
    }

    public void reconfigureCMS(ReplicationParams replicationParams)
    {
        ClusterMetadata metadata = ClusterMetadata.current();
        Set<NodeId> downNodes = new HashSet<>();
        for (InetAddressAndPort ep : metadata.directory.allJoinedEndpoints())
            if (!FailureDetector.instance.isAlive(ep))
                downNodes.add(metadata.directory.peerId(ep));
        PrepareCMSReconfiguration.Complex transformation = new PrepareCMSReconfiguration.Complex(replicationParams, downNodes);
        transformation.verify(metadata);

        ClusterMetadataService.instance()
                              .commit(transformation);

        InProgressSequences.finishInProgressSequences(ReconfigureCMS.SequenceKey.instance);
    }

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Verify CMS state first; if the CMS is already initialized, no upgrade is needed — skip upgradeFromGossip.
  2. Check logs / ClusterMetadata epochs to confirm the previous upgrade completed successfully instead of re-running.
  3. If a previous run half-finished, resolve the actual CMS state (which node owns the CMS) rather than forcing a re-upgrade.
  4. Guard the automation: only call upgradeFromGossip when the service state is GOSSIP.

Example fix

// before
service.upgradeFromGossip(ignored); // may run again on already-migrated cluster
// after
if (ClusterMetadataService.instance().state() == CMSState.GOSSIP)
    service.upgradeFromGossip(ignored);
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

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

Try / catch

try { service.upgradeFromGossip(ignored); } catch (IllegalStateException e) { logger.info("CMS already initialized, skipping upgrade"); }

Prevention

When it happens

Trigger: Calling upgradeFromGossip() a second time, or on a cluster where TCM was already enabled — detected by existing CMS members (existingMembers non-empty / CMS state no longer GOSSIP) after Election.instance.nominateSelf was previously executed.

Common situations: Upgrade automation re-run after a partial/failed run that already nominated a CMS; operator unsure whether the upgrade already happened and re-invokes the command; a cluster that was already migrated later being restored with a gossip-era script.

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