apache/cassandra · error · IllegalStateException

Migration already initiated by

Error message

Migration already initiated by 

What it means

Election.nominateSelf initiates the CMS migration protocol. Before starting, it calls updateInitiator(null, initiator) which only succeeds when no migration initiator is already recorded. If another node (or a previous run of this node) already initiated migration, an IllegalStateException naming the existing initiator is thrown.

Source

Thrown at src/java/org/apache/cassandra/tcm/migration/Election.java:100

    }

    private Election(MessageDelivery messaging)
    {
        this.messaging = messaging;
        this.prepareHandler = new PrepareHandler();
        this.abortHandler = new AbortHandler();
    }

    public void nominateSelf(Set<InetAddressAndPort> candidates, Set<InetAddressAndPort> ignoredEndpoints, ClusterMetadata metadata, boolean verifyAllPeersMetadata)
    {
        // Note: this is probably identical to the supplied metadata, but not guaranteed to be
        ClusterMetadata priorState = ClusterMetadata.current();
        Set<InetAddressAndPort> sendTo = new HashSet<>(candidates);
        sendTo.removeAll(ignoredEndpoints);
        sendTo.remove(FBUtilities.getBroadcastAddressAndPort());
        CMSInitializationRequest initializationRequest = new CMSInitializationRequest(FBUtilities.getBroadcastAddressAndPort(), UUID.randomUUID(), metadata);
        if (!updateInitiator(null, initializationRequest.initiator))
            throw new IllegalStateException("Migration already initiated by " + initiator.get());
        try
        {
            initiate(initializationRequest, sendTo, metadata, verifyAllPeersMetadata);
            finish(sendTo);
        }
        catch (Throwable e)
        {
            logger.error("Got error nominating self", e);
            abort(initializationRequest.initiator, sendTo);
            ClusterMetadata currentState = ClusterMetadata.current();

            // Clean up the system_cluster_metadata keyspace which may have been created by PRE_INITIALIZE_CMS
            Keyspace metaKeyspace = currentState.schema.getKeyspace(SchemaConstants.METADATA_KEYSPACE_NAME);
            if (metaKeyspace != null)
                metaKeyspace.unload(true);

            // Remove entries from system_schema tables
            Keyspaces.KeyspacesDiff diff = Keyspaces.diff(currentState.schema.getKeyspaces(), priorState.schema.getKeyspaces());

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Check the current initiator first (e.g. via nodetool cms or logs) and let the existing initiator finish
  2. If the recorded initiator node is dead, run Election/abortInitialization on that node with the expected initiator to reset state
  3. Wait for the in-flight migration to complete (state MIGRATED) before initiating again
  4. As a last resort, clear stale initiator state by re-running initialization with the correct --ignore list

Example fix

// before
// node A and node B both run: election.nominateSelf(...)  -> one throws
// after
// ensure only one initiator:
if (Election.initiator().isEmpty()) election.nominateSelf(...);
Defensive patterns

Strategy: try-catch

Validate before calling

if (Election.initiator().isPresent()) throw new IllegalStateException("Migration already in progress by " + Election.initiator().get());

Try / catch

try { election.nominateSelf(candidates, ignored, metadata, verify); } catch (IllegalStateException e) { logger.warn("Another initiator started migration: {}", e.getMessage()); }

Prevention

When it happens

Trigger: Calling nominateSelf (e.g. via nodetool cms initiate/self-nomination) while Election.initiator already holds a value from a prior or concurrent migration attempt.

Common situations: Two operators running the migration command simultaneously; retrying a failed migration whose initiator field was never cleared; a crashed node leaving stale initiator state.

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/3d4efa8a4ee8c665. Report an issue: GitHub.