apache/cassandra · warning

Host ID collision for

Error message

Host ID collision for {} between {} and {}; ignored {}

What it means

Warning logged by GossipCMSListener.onJoin when a gossiping endpoint announces a host ID that is already registered in the TCM Directory to a different endpoint, and the old endpoint has a more recent startup generation (compareEndpointStartup > 0). The listener concludes this is a host ID collision (two nodes claiming the same host ID) rather than an IP change, ignores the new endpoint, and returns without updating metadata.

Solutions

  1. Identify the duplicate node (from the log: hostId, oldEndpoint, endpoint) and regenerate the duplicated node's host ID / rebuild it from scratch with its own data directory
  2. Ensure node images or snapshots are never cloned while retaining the same host ID file; provision each node uniquely
  3. Stop the offending (ignored) endpoint so it does not keep announcing a colliding identity, then re-bootstrap it properly

Example fix

// before: cloned VM keeps the same host ID
cp -r /var/lib/cassandra /var/lib/cassandra-node2  # same host_id
// after: clear identity state so a new host ID is generated on the clone
rm /var/lib/cassandra-node2/hostid.txt && restart node2
Defensive patterns

Strategy: validation

Validate before calling

UUID hostId = UUID.fromString(hostIdValue.value);
NodeId existing = metadata.directory.nodeIdFromHostId(hostId);
if (existing != null && !metadata.directory.endpoint(existing).equals(endpoint)) {
    logger.warn("Host ID {} already bound to {} - refusing to accept {}", hostId, metadata.directory.endpoint(existing), endpoint);
    return;
}

Prevention

When it happens

Trigger: onJoin (via onAlive) processes an endpoint state carrying a hostId whose nodeId already maps to oldEndpoint, and Gossiper.instance.compareEndpointStartup(oldEndpoint, endpoint) > 0, i.e. the announced endpoint claims to be newer but the directory already binds that host ID elsewhere.

Common situations: Cloning a node's VM/disk image (host ID duplicated); restoring a node from a snapshot of another node; misconfigured cassandra-rackdc/host-id state after a failed bootstrap; two nodes accidentally started with the same data directory.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/tcm/migration/GossipCMSListener.java:67

        if (!metadata.epoch.is(Epoch.UPGRADE_GOSSIP))
            return;

        NodeId nodeId = metadata.directory.peerId(endpoint);
        if (nodeId == null)
        {
            VersionedValue hostIdValue = epState.getApplicationState(ApplicationState.HOST_ID);
            if (Gossiper.isHibernate(epState))
                return;

            if (hostIdValue != null)
            {
                UUID hostId = UUID.fromString(hostIdValue.value);
                nodeId = metadata.directory.nodeIdFromHostId(hostId);
                InetAddressAndPort oldEndpoint = metadata.directory.endpoint(nodeId);
                if (Gossiper.instance.compareEndpointStartup(oldEndpoint, endpoint) > 0)
                {
                    logger.warn("Host ID collision for {} between {} and {}; ignored {}", hostId, oldEndpoint, endpoint, endpoint);
                    return;
                }
                logger.info("Node {} (hostId = {}) changing IP from {} to {}", nodeId, hostId, oldEndpoint, endpoint);
                Gossiper.instance.removeEndpoint(oldEndpoint);
            }
            else
            {
                logger.warn("Could not find NodeId for endpoint {}", endpoint);
                return;
            }
        }
        // only thing that can change is the release version and addresses
        CassandraVersion gossipVersion = epState.getReleaseVersion();
        NodeAddresses newAddresses = GossipHelper.getAddressesFromEndpointState(endpoint, epState);
        while (true)
        {
            NodeVersion cmVersion = metadata.directory.versions.get(nodeId);
            if (cmVersion.cassandraVersion.equals(gossipVersion) && newAddresses.equals(metadata.directory.getNodeAddresses(nodeId)))

View on GitHub (pinned to 88fd0f6a0e)