apache/cassandra · error · IllegalStateException
Can't revert move from
Error message
Can't revert move from
What it means
Move.cancel reverts placed ranges step by step from MID_MOVE or START_MOVE back to the pre-move state. If the current step (next) is neither MID_MOVE nor START_MOVE, there is no defined way to revert, so cancel throws IllegalStateException naming the step. This prevents corrupting metadata by cancelling a move that is not in a revertible phase.
Source
Thrown at src/java/org/apache/cassandra/tcm/sequences/Move.java:445
ClusterMetadata metadata = ClusterMetadata.current();
return new ProgressBarrier(latestModification, metadata.directory.location(startMove.nodeId()), metadata.lockedRanges.locked.get(lockKey));
}
@Override
public ClusterMetadata.Transformer cancel(ClusterMetadata metadata)
{
DataPlacements placements = metadata.placements();
switch (next)
{
case FINISH_MOVE:
placements = midMove.inverseDelta().apply(metadata.directory, metadata.nextEpoch(), placements);
case MID_MOVE:
placements = startMove.inverseDelta().apply(metadata.directory, metadata.nextEpoch(), placements);
case START_MOVE:
placements = toSplitRanges.invert().apply(metadata.directory, metadata.nextEpoch(), placements);
break;
default:
throw new IllegalStateException("Can't revert move from " + next);
}
LockedRanges newLockedRanges = metadata.lockedRanges.unlock(lockKey);
return metadata.transformer()
.withNodeState(startMove.nodeId(), NodeState.JOINED)
.with(placements)
.with(newLockedRanges);
}
/**
* Returns a mapping of destination -> source*, where the destination is the node that needs to stream from source
*
* there can be multiple sources for each destination
*/
private static MovementMap movementMap(IFailureDetector fd, DataPlacements placements, EndpointLookup endpointLookup, PlacementDeltas toSplitRanges, PlacementDeltas toStart, PlacementDeltas midDeltas, boolean strictConsistency)
{
MovementMap.Builder allMovements = MovementMap.builder();
toStart.forEach((params, delta) -> {View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Check the move's current step before cancelling; a completed/finished move cannot be reverted via cancel
- If the move is at FINISH_MOVE, let it complete or use the appropriate completion/rollback path
- Retry cancel promptly after the move is observed in START_MOVE/MID_MOVE if reverting is truly required
- Verify TCM metadata state of the sequence to confirm which step it is actually on
Example fix
// before
move.cancel();
// after
if (move.currentStep() == Move.MoveStep.START_MOVE || move.currentStep() == Move.MoveStep.MID_MOVE)
move.cancel();
else
logger.warn("Move is at {} and cannot be reverted", move.currentStep()); Defensive patterns
Strategy: validation
Validate before calling
Move.MoveStep step = move.currentStep();
if (step != Move.MoveStep.START_MOVE && step != Move.MoveStep.MID_MOVE)
throw new IllegalStateException("Move not revertible at " + step); Try / catch
try { move.cancel(); } catch (IllegalStateException e) { logger.warn("Cannot cancel move: {}", e.getMessage()); inspectSequenceState(); } Prevention
- Check the sequence's current step before issuing cancel
- Don't cancel after FINISH_MOVE; let it complete
- Automate cancellation promptly after detecting a stuck START/MID move
When it happens
Trigger: Calling cancel on a Move sequence whose current MultiStepOperation step is FINISH_MOVE, COMPLETED, or otherwise not in the START_MOVE/MID_MOVE phases handled by the switch.
Common situations: Operator tries to cancel a move after it already finished; race between the move completing and the cancel command arriving; automation retrying cancel after the move already committed its final step.
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
- Node should be either source or destination in the movement
- %s function resource has no function name
- Root-level resource can't have a parent
- ROOT data resource has no keyspace
- stream can only move forward
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/19d998d08b37b6f5.
Report an issue: GitHub.