apache/cassandra · critical · IllegalStateException

Cannot replace same address when accord transactions are ena

Error message

Cannot replace same address when accord transactions are enabled.

What it means

During TCM-based startup, a node configured with storage_port identical to an existing node's address (replace-address pointing at itself) cannot perform the 'replace same address' operation when Accord transactions are enabled. Accord binds transaction state to a persistent NodeId; reusing the address with the same NodeId would corrupt transaction safety, so the JVM throws IllegalStateException deliberately with a TODO to add a supported mode.

Source

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

                metadata = ClusterMetadata.current();

                if (metadata.directory.peerState(self) == JOINED)
                    SystemKeyspace.setBootstrapState(SystemKeyspace.BootstrapState.COMPLETED);
                else
                {
                    StorageService.instance.markBootstrapFailed();
                    logger.info("Did not finish joining the ring; node state is {}, bootstrap state is {}",
                                metadata.directory.peerState(self),
                                SystemKeyspace.getBootstrapState());
                    break;
                }
            case JOINED:
                if (StorageService.isReplacingSameAddress())
                {
                    if (DatabaseDescriptor.getAccordTransactionsEnabled())
                    {
                        // TODO (required): we need to support a mode that changes the NodeId when replacing the same address for accord transaction safety
                        throw new IllegalStateException("Cannot replace same address when accord transactions are enabled.");
                    }

                    ReplaceSameAddress.streamData(self, metadata, shouldBootstrap, finishJoiningRing);
                }

                // JOINED appears before BOOTSTRAPPING & BOOT_REPLACE so we can fall
                // through when we start as REGISTERED/LEFT and complete a full startup
                logger.info("{}", StorageService.Mode.NORMAL);
                break;
            case BOOTSTRAPPING:
            case BOOT_REPLACING:
                if (finishJoiningRing)
                {
                    throw new IllegalStateException("Expected to complete startup sequence, but did not. " +
                                                    "Can't proceed from the state " + metadata.directory.peerState(self));
                }
                break;
            case LEAVING:

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Disable Accord transactions (set the accord transactions_enabled property to false) before performing the same-address replacement, then re-enable after the node rejoins
  2. Perform a normal (different-address) replacement, or decommission/removal + fresh bootstrap instead of replace-same-address
  3. Upgrade/pick a Cassandra version that implements the NodeId-change-on-replace mode (the code TODO), if available
  4. If the data on disk is disposable, wipe data dirs and bootstrap as a new node

Example fix

// before (cassandra.yaml / properties)
cassandra.replace_address=10.0.0.5   # same as this node
accord.transactions_enabled=true
// after
accord.transactions_enabled=false   # allows ReplaceSameAddress path
# ... after successful rejoin, re-enable accord.transactions_enabled=true
Defensive patterns

Strategy: validation

Validate before calling

if (DatabaseDescriptor.isReplacingSameAddress() && DatabaseDescriptor.getAccordTransactionsEnabled())
    throw new IllegalArgumentException("Disable accord transactions or use a different replace address");

Prevention

When it happens

Trigger: Setting cassandra.replace_address (or replace_address_first_boot) to the node's OWN broadcast address while cassandra.accord.transactions_enabled is true, then starting the node in state JOINED.

Common situations: Operators recovering a dead node by pointing replace_address at itself on ephemeral infrastructure (e.g. k8s StatefulSet restarts), combined with a cluster where Accord (distributed transactions) is enabled after an upgrade.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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