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
- Verify CMS state first; if the CMS is already initialized, no upgrade is needed — skip upgradeFromGossip.
- Check logs / ClusterMetadata epochs to confirm the previous upgrade completed successfully instead of re-running.
- If a previous run half-finished, resolve the actual CMS state (which node owns the CMS) rather than forcing a re-upgrade.
- 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
- Make upgrade scripts idempotent by checking CMS state first
- Log migration completion so operators know it already ran
- Only invoke upgradeFromGossip once per cluster
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
- Initial CMS node needs to be fully joined, not: %s
- Ignored host(s) %s don't exist in the cluster
- All nodes are not yet upgraded - %s is running %s
- Tried to commit when in gossip mode
- Illegal state:
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/f4f001c13780e7bb.
Report an issue: GitHub.