{"record":{"id":"83a366c8dbc34f31","repo":"apache/cassandra","slug":"host-id-collision-for-between-and-ignore","errorCode":null,"errorMessage":"Host ID collision for {} between {} and {}; ignored {}","messagePattern":"Host ID collision for (.+?) between (.+?) and (.+?); ignored (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/java/org/apache/cassandra/tcm/migration/GossipCMSListener.java","lineNumber":67,"sourceCode":"\n        if (!metadata.epoch.is(Epoch.UPGRADE_GOSSIP))\n            return;\n\n        NodeId nodeId = metadata.directory.peerId(endpoint);\n        if (nodeId == null)\n        {\n            VersionedValue hostIdValue = epState.getApplicationState(ApplicationState.HOST_ID);\n            if (Gossiper.isHibernate(epState))\n                return;\n\n            if (hostIdValue != null)\n            {\n                UUID hostId = UUID.fromString(hostIdValue.value);\n                nodeId = metadata.directory.nodeIdFromHostId(hostId);\n                InetAddressAndPort oldEndpoint = metadata.directory.endpoint(nodeId);\n                if (Gossiper.instance.compareEndpointStartup(oldEndpoint, endpoint) > 0)\n                {\n                    logger.warn(\"Host ID collision for {} between {} and {}; ignored {}\", hostId, oldEndpoint, endpoint, endpoint);\n                    return;\n                }\n                logger.info(\"Node {} (hostId = {}) changing IP from {} to {}\", nodeId, hostId, oldEndpoint, endpoint);\n                Gossiper.instance.removeEndpoint(oldEndpoint);\n            }\n            else\n            {\n                logger.warn(\"Could not find NodeId for endpoint {}\", endpoint);\n                return;\n            }\n        }\n        // only thing that can change is the release version and addresses\n        CassandraVersion gossipVersion = epState.getReleaseVersion();\n        NodeAddresses newAddresses = GossipHelper.getAddressesFromEndpointState(endpoint, epState);\n        while (true)\n        {\n            NodeVersion cmVersion = metadata.directory.versions.get(nodeId);\n            if (cmVersion.cassandraVersion.equals(gossipVersion) && newAddresses.equals(metadata.directory.getNodeAddresses(nodeId)))","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/migration/GossipCMSListener.java#L49-L85","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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","Ensure node images or snapshots are never cloned while retaining the same host ID file; provision each node uniquely","Stop the offending (ignored) endpoint so it does not keep announcing a colliding identity, then re-bootstrap it properly"],"exampleFix":"// before: cloned VM keeps the same host ID\ncp -r /var/lib/cassandra /var/lib/cassandra-node2  # same host_id\n// after: clear identity state so a new host ID is generated on the clone\nrm /var/lib/cassandra-node2/hostid.txt && restart node2","handlingStrategy":"validation","validationCode":"UUID hostId = UUID.fromString(hostIdValue.value);\nNodeId existing = metadata.directory.nodeIdFromHostId(hostId);\nif (existing != null && !metadata.directory.endpoint(existing).equals(endpoint)) {\n    logger.warn(\"Host ID {} already bound to {} - refusing to accept {}\", hostId, metadata.directory.endpoint(existing), endpoint);\n    return;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never clone VMs/disks of provisioned nodes; always generate fresh host IDs","Keep cassandra data/identity files out of golden images","Alert on duplicate host IDs in cluster membership monitoring"],"tags":["host-id","cluster-membership","gossip","identity-collision"],"backgroundTag":"internal-invariant-violation","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}