apache/cassandra · error · java.lang.IllegalStateException

A node with address already exists, cancelling join. Use…

Error message

A node with address %s already exists, cancelling join. Use cassandra.replace_address if you want to replace this node.

What it means

Thrown during Register.register() when the broadcast address the node is joining with already maps to an existing peer in cluster metadata, and the node is not configured to replace that node. CMS refuses to register a duplicate address to keep the directory consistent.

Solutions

  1. Set cassandra.replace_address (or replace_node) to indicate intentional replacement of the existing node
  2. Give the new node a unique broadcast_address/port not present in the cluster
  3. If the old node is dead, remove it from the cluster (nodetool decommission/removenode) before reusing the address
  4. Verify with nodetool status that no live/registered node holds that IP

Example fix

// before
cassandra.broadcast_address=10.0.0.7 // already used by node2
// after
cassandra.broadcast_address=10.0.0.9 // unused address
// or, for intentional replacement:
-Dcassandra.replace_address=10.0.0.7
Defensive patterns

Strategy: validation

Validate before calling

// before starting a node, check the address is free
boolean taken = ClusterMetadata.current().directory.peerId(broadcastAddress) != null;
if (taken && !isReplacementConfigured()) throw new IllegalStateException("address in use; set replace_address or pick a new IP");

Try / catch

try { CMS.commit(registration); } catch (IllegalStateException e) { if (e.getMessage().contains("already exists")) { /* resolve duplicate address or set replace_address */ } else throw e; }

Prevention

When it happens

Trigger: Calling register() where directory.peerId(broadcastAddress) is non-null but the node is not doing an explicit replacement (no cassandra.replace_address / replace_node configured).

Common situations: Cloning a VM/image with the same IP as an existing node; a previously replaced node's old entry still in metadata; accidental reuse of an assigned IP; starting a second node with a misconfigured broadcast_address.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/tcm/transformations/Register.java:152

    {
        return register(nodeAddresses, DatabaseDescriptor.getLocator().local(), nodeVersion);
    }

    private static NodeId register(NodeAddresses nodeAddresses, Location location, NodeVersion nodeVersion)
    {
        ClusterMetadata metadata = ClusterMetadata.current();
        DatabaseDescriptor.getInitialLocationProvider().validate(metadata);
        NodeId nodeId = metadata.directory.peerId(nodeAddresses.broadcastAddress);
        if (nodeId == null || metadata.directory.peerState(nodeId) == NodeState.LEFT)
        {
            if (nodeId != null)
                ClusterMetadataService.instance().commit(new Unregister(nodeId, EnumSet.of(NodeState.LEFT), ClusterMetadataService.instance().placementProvider()));
            Register registration = new Register(nodeAddresses, location, nodeVersion);
            nodeId = ClusterMetadataService.instance().commit(registration).directory.peerId(nodeAddresses.broadcastAddress);
        }
        else
        {
            throw new IllegalStateException(String.format("A node with address %s already exists, cancelling join. Use cassandra.replace_address if you want to replace this node.", nodeAddresses.broadcastAddress));
        }

        logger.info("Registered with endpoint {}, node id: {}", nodeAddresses.broadcastAddress, nodeId);
        return nodeId;
    }

    private static NodeId register(boolean force)
    {
        // Try to recover node ID from the system keyspace
        UUID localHostId = SystemKeyspace.getLocalHostId();
        Directory directory = ClusterMetadata.current().directory;
        if (force || localHostId == null)
        {
            NodeId nodeId = register(NodeAddresses.current());
            localHostId = nodeId.toUUID();
            SystemKeyspace.setLocalHostId(localHostId);
            logger.info("New node ID obtained {}, (Note: This should happen exactly once per node)", localHostId);
            return nodeId;

View on GitHub (pinned to 88fd0f6a0e)