apache/cassandra · error · IllegalStateException

Can only initialize cluster identifier once, but it was…

Error message

Can only initialize cluster identifier once, but it was already set to %d

What it means

Thrown by ClusterMetadata.forceInitializedState when the cluster identifier (metadataIdentifier) has already been initialized. The identifier can only be set once, transitioning metadata from the empty/uninitialized state; a second call would silently re-identify the cluster.

Solutions

  1. Skip the initialization if metadataIdentifier is already set (idempotency check before the call).
  2. Load the existing cluster metadata instead of re-initializing.
  3. Remove duplicate initialization calls from retry logic.

Example fix

// before
metadata.forceInitializedState(id, addresses, version, location);
// after
if (metadata.metadataIdentifier == ClusterMetadata.EMPTY_METADATA_IDENTIFIER)
    metadata.forceInitializedState(id, addresses, version, location);
Defensive patterns

Strategy: validation

Validate before calling

if (metadata.metadataIdentifier != ClusterMetadata.EMPTY_METADATA_IDENTIFIER) { /* already initialized */ return; }

Try / catch

try { metadata.forceInitializedState(id, addr, ver, loc); } catch (IllegalStateException e) { logger.info("Cluster already initialized: {}", e.getMessage()); }

Prevention

When it happens

Trigger: Calling forceInitializedState a second time on a ClusterMetadata whose metadataIdentifier != EMPTY_METADATA_IDENTIFIER.

Common situations: Re-running cluster bootstrap or metadata initialization tooling twice, replaying an initialization transformation from a snapshot/log, or a retry path re-invoking initialization after a partially successful run.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/tcm/ClusterMetadata.java:483

    }

    /**
     * Produce a ClusterMetadata suitable for use as the base state in the INITIALIZE_CMS transformation. This should
     * only be used on the first CMS node when bootstrapping the CMS after upgrade or in a brand new cluster.
     * @param clusterIdentifier Unique identifier for split brain detection & protection
     * @param addresses The NodeAddresses of the first CMS node.
     * @param version Version info for the first CMS node.
     * @param location The rack & DC of the first CMS node.
     * @return ClusterMetadata instance in the correct state to constitute the base state of the INITIALIZE_CMS
     *         transformation
     */
    public ClusterMetadata forceInitializedState(int clusterIdentifier,
                                                 NodeAddresses addresses,
                                                 NodeVersion version,
                                                 Location location)
    {
        if (this.metadataIdentifier != EMPTY_METADATA_IDENTIFIER)
            throw new IllegalStateException(String.format("Can only initialize cluster identifier once, but it was already set to %d", this.metadataIdentifier));

        if (clusterIdentifier == EMPTY_METADATA_IDENTIFIER)
            throw new IllegalArgumentException("Can not initialize cluster with empty cluster identifier");

        if (this.epoch.isAfter(Epoch.FIRST))
            throw new IllegalStateException(String.format("Can only initialize cluster identifier during epoch %d, but current epoch is %d", Epoch.FIRST.getEpoch(), epoch.getEpoch()));

        // Maybe register the first CMS node. If upgrading from gossip, this should be a no-op
        Directory withRegistered = directory.with(addresses, location, version);
        NodeId firstNode = withRegistered.peerId(addresses.broadcastAddress);
        if (firstNode == null)
            throw new IllegalStateException("Failed to find first CMS node in directory");

        CMSMembership initialCMS = cmsMembership.startJoining(firstNode).finishJoining(firstNode);
        return new ClusterMetadata(clusterIdentifier,
                                   epoch,
                                   partitioner,
                                   schema,

View on GitHub (pinned to 88fd0f6a0e)