apache/cassandra · critical · IllegalStateException

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

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.

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)

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.