apache/cassandra · critical · IllegalStateException

NodeId does not match locally set one. Check for the IP…

Error message

NodeId does not match locally set one. Check for the IP address collision: %s vs %s %s.

What it means

During non-CMS startup, Startup.initializeAsNonCmsNode verifies with an existing cluster member that the NodeId/HostId the cluster has recorded for this node's broadcast address matches the locally persisted nodeId. On mismatch it throws this IllegalStateException, explicitly warning about a possible IP address collision: two different nodes have claimed (or are claiming) the same broadcast address, or the local hostid file is stale relative to cluster state.

Solutions

  1. Confirm no other live node holds this broadcast address (nodetool status / system.peers_v2 on a healthy node).
  2. If this is genuinely a new node on a reused IP, remove the stale cluster registration: decommission the dead node or use cms REMOVENODE for the old hostid.
  3. Delete the stale local hostid file (hostid.txt in the data directory) only if this node is truly a fresh member, then restart so it registers anew.
  4. Fix broadcast_address/broadcast_and_listen configuration so the address is unique in the cluster.
  5. Never edit cluster metadata directly while both nodes are live — take one of them down first.

Example fix

// before: node reuses an address already registered to another hostid
cassandra-env: BROADCAST=10.0.0.7  // cluster has 10.0.0.7 -> hostid X, local hostid Y
// after: unique address or cleaned registration
BROADCAST=10.0.0.42  // or: remove old node (hostid X) before starting this one
Defensive patterns

Strategy: validation

Validate before calling

// before startup, verify no other node claims this IP with a different hostid
UUID local = FBUtilities.getBroadcastAddressAndPort().equals(addr) ? ClusterMetadataService.instance().hostIdFor(addr) : null;
if (local != null && !local.equals(localHostId)) throw new IllegalStateException("Address collision detected");

Try / catch

try { Startup.initializeAsNonCmsNode(...); }
catch (IllegalStateException e) {
    if (e.getMessage().contains("IP address collision")) {
        // halt startup, alert operator: do NOT delete hostid blindly
        failFast(e);
    } else throw e;
}

Prevention

When it happens

Trigger: initializeAsNonCmsNode fetches the remote view and finds currentHostId != nodeId.toUUID(); the node's IP was reassigned to different hardware; a stale hostid file persisted locally conflicts with the cluster's registration; the broadcast_address configuration was changed to overlap another node.

Common situations: IP reuse after replacing a node without decommissioning the old one; VM/container IPs recycled between clusters; restored node reusing an old data directory on an address already taken; DNS/hostname resolution pointing multiple nodes at one address.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/tcm/Startup.java:245

                                                                      wrapProcessor,
                                                                      ClusterMetadataService::state,
                                                                      logSpec));
        ClusterMetadataService.instance().log().ready();
        NodeId nodeId = ClusterMetadata.current().myNodeId();
        UUID currentHostId = SystemKeyspace.getLocalHostId();
        if (nodeId != NodeId.UNREGISTERED && !Objects.equals(nodeId.toUUID(), currentHostId))
        {
            if (currentHostId == null)
            {
                logger.info("Taking over the host ID: {}, replacing address {}", nodeId.toUUID(), FBUtilities.getBroadcastAddressAndPort());
                SystemKeyspace.setLocalHostId(nodeId.toUUID());
                return;
            }

            String error = String.format("NodeId does not match locally set one. Check for the IP address collision: %s vs %s %s.",
                                         currentHostId, nodeId.toUUID(), FBUtilities.getBroadcastAddressAndPort());
            logger.error(error);
            throw new IllegalStateException(error);
        }
    }


    /**
     * If the broadcast address of this node has changed, we must verify the endpoints it knows for
     * the members of the CMS are still reachable and valid. This is necessary for the node to submit
     * a STARTUP transformation which updates its broadcast address in ClusterMetadata.
     *
     * If the node is itself a CMS member, it is also a requirement to be able to contact a
     * majority of the other CMS members in order to perform the serial reads and writes which
     * constitute committing to and fetching from the distributed metadata log.
     *
     * To do this, we use a simple protocol:
     * 1. For each CMS member in our replayed ClusterMetadata, ping the associated broadcast address
     *   to query for id of the node at that address. This determines whether the endpoint still
     *   belongs to that same node (which is/was a CMS member).
     * 2. While we don't have confirmed current addresses for a majority of CMS nodes:

View on GitHub (pinned to 88fd0f6a0e)