apache/cassandra · warning
Cluster metadata identifier mismatch from
Error message
Cluster metadata identifier mismatch from {} {}!={} What it means
A logger.warn (not an exception): in accrual-enabled clusters the gossip SYN carries a cluster metadata identifier; doVerb drops the message when the sender's metadataId is neither EMPTY_METADATA_IDENTIFIER nor equal to the local ClusterMetadata.current().metadataIdentifier. This guards against gossiping with nodes that hold a different cluster metadata epoch/lineage (TCM-era split-brain protection).
Solutions
- Verify cluster identity on both sides (`nodetool describecluster` shows cluster metadata id); if the peer belongs to another cluster, remove it from the network.
- For a cloned/reset node, wipe its data and commitlog dirs and re-bootstrap so it syncs with the current cluster metadata log.
- Ensure the metadata log (replay positions/seed nodes) is intact; if cluster metadata diverged, follow the documented recovery procedure for TCM.
- Prevent recurrences by provisioning nodes from images that never contain another cluster's metadata state.
Example fix
// before: node cloned from a template containing old cluster metadata // after: clean data dirs, then start so it joins current metadata rm -rf /var/lib/cassandra/data/* /var/lib/cassandra/commitlog/* service cassandra start // node syncs ClusterMetadata from the log
Defensive patterns
Strategy: validation
Validate before calling
// never provision nodes from images containing another cluster's metadata state // compare metadata ids across nodes: nodetool describecluster # all nodes should report the same cluster metadata id
Prevention
- Provision from clean images without prior cluster metadata.
- Wipe data/commitlog dirs when re-imaging or cloning nodes.
- Monitor `nodetool describecluster` for divergent metadata ids.
- Follow the documented TCM recovery procedure if cluster metadata diverges.
When it happens
Trigger: A node whose ClusterMetadata identifier diverges from the local node (e.g., a node that was reset/reseeded from a different metadata log, or from a cloned/split cluster) sends a gossip SYN. Nodes with EMPTY_METADATA_IDENTIFIER are still accepted so fresh joins can gossip.
Common situations: Cloning VMs/disks to provision nodes so multiple nodes claim the same or divergent metadata lineage; restoring a node from a backup taken at a different metadata epoch; network partition resolving with a diverged metadata state; mixing nodes from accidentally split clusters.
Related errors
- All nodes are not yet upgraded
- Another sequence of kind
- Bad NodeState
- broadcast_address cannot be a wildcard address (
- Can not add a new in-progress sequence for
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/5f7fbbb20d8f4112.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/gms/GossipDigestSynVerbHandler.java:70
GossipDigestSyn gDigestMessage = message.payload;
/* If the message is from a different cluster throw it away. */
if (!gDigestMessage.clusterId.equals(DatabaseDescriptor.getClusterName()))
{
logger.warn("ClusterName mismatch from {} {}!={}", from, gDigestMessage.clusterId, DatabaseDescriptor.getClusterName());
return;
}
if (gDigestMessage.partioner != null && !gDigestMessage.partioner.equals(DatabaseDescriptor.getPartitionerName()))
{
logger.warn("Partitioner mismatch from {} {}!={}", from, gDigestMessage.partioner, DatabaseDescriptor.getPartitionerName());
return;
}
if (gDigestMessage.metadataId != ClusterMetadata.EMPTY_METADATA_IDENTIFIER
&& gDigestMessage.metadataId != ClusterMetadata.current().metadataIdentifier)
{
logger.warn("Cluster metadata identifier mismatch from {} {}!={}", from, gDigestMessage.metadataId, ClusterMetadata.current().metadataIdentifier);
return;
}
List<GossipDigest> gDigestList = gDigestMessage.getGossipDigests();
// if the syn comes from a peer performing a shadow round and this node is
// also currently in a shadow round, send back a minimal ack. This node must
// be in the sender's seed list and doing this allows the sender to
// differentiate between seeds from which it is partitioned and those which
// are in their shadow round
if (!Gossiper.instance.isEnabled() && NewGossiper.instance.isInShadowRound())
{
// a genuine syn (as opposed to one from a node currently
// doing a shadow round) will always contain > 0 digests
if (gDigestList.size() > 0)
{
logger.debug("Ignoring non-empty GossipDigestSynMessage because currently in gossip shadow round");
return;
}View on GitHub (pinned to 88fd0f6a0e)