apache/cassandra · error · RuntimeException
Unable to move
Error message
Unable to move
What it means
executeNext wraps the move's streaming/metadata step; an ExecutionException from the underlying future is rethrown as RuntimeException("Unable to move", e) after marking the move as failed via StorageService.markMoveFailed(). The original cause is attached, so the root reason (streaming failure, timeout, node down) is in the cause chain. Other exceptions are marked failed and rethrown unchanged.
Source
Thrown at src/java/org/apache/cassandra/tcm/sequences/Move.java:375
throw new IllegalStateException("Node should be either source or destination in the movement map " + endpoints);
}
}
StreamResultFuture streamResult = streamPlan.execute();
Future<?> accordReady = AccordService.instance().epochReadyFor(metadata, EpochReady::reads);
Future<?> ready = FutureCombiner.allOf(streamResult, accordReady);
ready.get();
StorageService.instance.repairPaxosForTopologyChange("move");
}
catch (InterruptedException e)
{
return continuable();
}
catch (ExecutionException e)
{
StorageService.instance.markMoveFailed();
throw new RuntimeException("Unable to move", e);
}
catch (Exception e)
{
StorageService.instance.markMoveFailed();
throw e;
}
try
{
ClusterMetadataService.instance().commit(midMove);
}
catch (Throwable t)
{
logger.warn("Exception committing midMove, will retry on next TCM epoch advance", t);
JVMStabilityInspector.inspectThrowable(t);
return continuable();
}
break;View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Inspect the cause chain of the RuntimeException to find the true failure (streaming error, timeout, node down)
- Fix the underlying issue (restart the failed node, restore connectivity, free disk space)
- Re-attempt the move once the cluster is healthy; Move supports retrying from a continuable state
- Check StorageService move-failed state and logs for the streaming session that failed
Example fix
// before
catch (ExecutionException e)
{
StorageService.instance.markMoveFailed();
throw new RuntimeException("Unable to move", e);
}
// after
catch (ExecutionException e)
{
StorageService.instance.markMoveFailed();
throw new RuntimeException("Unable to move: " + e.getCause().getMessage(), e.getCause());
} Defensive patterns
Strategy: try-catch
Try / catch
try { move.execute(); } catch (RuntimeException e) { Throwable root = e; while (root.getCause() != null) root = root.getCause(); logger.error("Move failed, root cause: {}", root.getMessage(), root); StorageService.instance.markMoveFailed(); } Prevention
- Ensure all nodes are UP before starting a move
- Check disk space and network stability on streaming endpoints
- Read the cause chain — 'Unable to move' is always a wrapper
- Retry the move only after fixing the root failure
When it happens
Trigger: Any ExecutionException surfaced by the move execution future: streaming session failure, peer node down during range transfer, timeout waiting for the move step, or a rejected transformation during the move.
Common situations: Target/source node crashes mid-move; network partition interrupts streaming; cluster busy with another topology change causing a wait/timeout; disk space exhaustion on a streaming endpoint.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Node should be either source or destination in the movement
- Unable to find sufficient sources for streaming range " + tr
- Source %s for %s is not remaining as a replica after the mov
- Could not finish join for during replacement
- [{}] Received {} from {} containing ranges {} outside valid
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/5ac5b578eadb4ab5.
Report an issue: GitHub.