apache/cassandra · error · IllegalStateException
Can't finish migration, initiator=
Error message
Can't finish migration, initiator=
What it means
Election.finish finalizes CMS migration by transitioning the initiator state. If the recorded initiator is neither this node's successful chain nor in the expected MIGRATING state (currentInitiator is stale or belongs to someone else), finish() throws IllegalStateException, leaving migration incomplete.
Solutions
- Inspect logs to identify the actual recorded initiator and let that node drive migration to completion
- Run abortInitialization with the correct expected initiator to clear stale state, then nominateSelf again
- Ensure only one operator executes the migration command at a time
- Retry after state is cleared; verify initiator() is null before initiating
Example fix
// before
// concurrent nominateSelf on two nodes -> finish() sees foreign initiator
// after
// single coordinator:
if (!updateInitiator(null, FBUtilities.getBroadcastAddressAndPort()))
throw new IllegalStateException("already initiated by " + initiator.get()); Defensive patterns
Strategy: try-catch
Validate before calling
Object current = Election.initiator(); if (current != null && current != MIGRATING && !current.equals(self)) throw new IllegalStateException("Foreign initiator: " + current); Try / catch
try { nominateSelf(...); } catch (IllegalStateException e) { // clear state via abortInitialization with the correct initiator, then retry } Prevention
- Serialize migration attempts: one initiator at a time
- Clear initiator state (abortInitialization) after aborted runs
- Confirm initiator() is null before starting a new migration
When it happens
Trigger: nominateSelf reaches finish() but the recorded initiator was concurrently changed (another node initiated, or a prior aborted attempt left an unexpected initiator value).
Common situations: Concurrent migration attempts from two nodes; a retried nominateSelf after a partially completed earlier run; state not reset after abort().
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
- Current initiator [ ] does not match provided - run this…
- Addresses differ: !=
- Can only initialize cluster identifier during epoch
- Can't commit transformations when running in gossip mode…
- Can't ignore local host
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/a71f3315edcb935a.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/tcm/migration/Election.java:163
throw new IllegalStateException(msg);
}
}
}
private void finish(Set<InetAddressAndPort> sendTo)
{
CMSInitializationRequest.Initiator currentInitiator = initiator.get();
if (currentInitiator != null &&
Objects.equals(currentInitiator.endpoint, FBUtilities.getBroadcastAddressAndPort()) &&
initiator.compareAndSet(currentInitiator, MIGRATING))
{
Startup.initializeAsFirstCMSNode();
updateInitiator(MIGRATING, MIGRATED);
MessageDelivery.fanoutAndWait(messaging, sendTo, Verb.TCM_NOTIFY_REQ, DistributedMetadataLogKeyspace.getLogState(Epoch.EMPTY, false));
}
else
{
throw new IllegalStateException("Can't finish migration, initiator="+currentInitiator);
}
}
private void abort(CMSInitializationRequest.Initiator init, Set<InetAddressAndPort> sendTo)
{
logger.info("Aborting migration");
CMSInitializationRequest.Initiator previous = initiator.getAndSet(null);
logger.info("Reset local initiator state (was {}), sending abort message to peers", previous);
for (InetAddressAndPort ep : sendTo)
messaging.send(Message.out(Verb.TCM_ABORT_MIG, init), ep);
}
public CMSInitializationRequest.Initiator initiator()
{
return initiator.get();
}
public void migrated()View on GitHub (pinned to 88fd0f6a0e)