apache/cassandra · error · IllegalStateException
Can't revert join from
Error message
Can't revert join from
What it means
BootstrapAndJoin.cancel reverts a partially applied join sequence by inverting the transformations recorded so far. The switch over the sequence's current step (next) handles MID_JOIN/START_JOIN; IllegalStateException is thrown from the default branch when cancellation is attempted from any other state (e.g. FINISH_JOIN or an unexpected step), meaning the join cannot be reverted from that point.
Source
Thrown at src/java/org/apache/cassandra/tcm/sequences/BootstrapAndJoin.java:342
return new ProgressBarrier(latestModification, metadata.directory.location(startJoin.nodeId()), metadata.lockedRanges.locked.get(lockKey));
}
@Override
public ClusterMetadata.Transformer cancel(ClusterMetadata metadata)
{
DataPlacements placements = metadata.placements();
switch (next)
{
// need to undo MID_JOIN and START_JOIN, then merge the ranges split by PrepareJoin
case FINISH_JOIN:
placements = midJoin.inverseDelta().apply(metadata.directory, metadata.nextEpoch(), placements);
case MID_JOIN:
placements = startJoin.inverseDelta().apply(metadata.directory, metadata.nextEpoch(), placements);
case START_JOIN:
placements = toSplitRanges.invert().apply(metadata.directory, metadata.nextEpoch(), placements);
break;
default:
throw new IllegalStateException("Can't revert join from " + next);
}
LockedRanges newLockedRanges = metadata.lockedRanges.unlock(lockKey);
return metadata.transformer()
.withNodeState(startJoin.nodeId(), NodeState.REGISTERED)
.with(placements)
.with(newLockedRanges);
}
public BootstrapAndJoin finishJoiningRing()
{
return new BootstrapAndJoin(latestModification, lockKey, toSplitRanges,
next, startJoin, midJoin, finishJoin,
true, false);
}
@VisibleForTesting
public Pair<MovementMap, MovementMap> getMovementMaps(ClusterMetadata metadata)
{View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Check the current step (nextStep()/state) before calling cancel and only revert from START_JOIN or MID_JOIN; if the join finished, use the appropriate removal/decommission sequence instead
- If cancellation raced and the join completed, treat the node as joined and run decommission to remove it
- Re-read ClusterMetadata to get the authoritative node state and re-issue the cancellation against the current sequence
- Report/log this as an unexpected state if next is neither of the handled kinds, since it may indicate metadata corruption
Example fix
// before
bootstrapAndJoin.cancel(metadata);
// after
if (bootstrapAndJoin.nextStep() == Transformation.Kind.FINISH_JOIN)
// join already committed; use decommission instead
else
bootstrapAndJoin.cancel(metadata); Defensive patterns
Strategy: try-catch
Validate before calling
Transformation.Kind step = sequence.nextStep();
if (step != Transformation.Kind.START_JOIN && step != Transformation.Kind.MID_JOIN)
throw new IllegalStateException("cannot revert join from step " + step); Try / catch
try { seq.cancel(metadata); } catch (IllegalStateException e) { /* if FINISH_JOIN: treat as joined, run decommission instead */ } Prevention
- Check the sequence's current step before attempting cancellation
- Avoid concurrent/racing cancel invocations
- Track join completion to switch cleanup strategy to decommission
When it happens
Trigger: Calling cancel() on a BootstrapAndJoin whose Transformation.Kind state is not START_JOIN or MID_JOIN — e.g. the join already reached FINISH_JOIN, or the sequence object's state is uninitialized/corrupted.
Common situations: A user retries cancellation after the join already committed its final transformation; concurrent retries race so the second cancel observes a later state; a failed join plan leaves state at a kind the revert logic does not expect.
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
- Step %s is invalid for sequence %s
- Expected to complete startup sequence, but did not. Can't pr
- Can't revert replacement from
- Step %s is invalid for sequence %s
- Can not resume bootstrap as join sequence has not been start
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/0c17e14ab99b2612.
Report an issue: GitHub.