apache/cassandra · error · RuntimeException
Error occurred attempting to finish migration for…
Error message
Error occurred attempting to finish migration for keyspace(s) %s tables %s and ranges %s
What it means
ConsensusMigrationAdmin's execute launches the repair rounds that finish a Paxos-to-Accord (or reverse) consensus migration via probe.startAndBlockOnAsyncRepairs; an IOException there is wrapped with a message naming the keyspaces, tables, and ranges involved. It means the blocking async-repair phase of the migration failed at the transport/remote level.
Solutions
- Ensure all nodes in the migration ranges are up and reachable, then re-run the finish command (it is idempotent — a second call does nothing if repairs already committed).
- Check repair history / logs (`nodetool netstats`, system protocol logs) for the failing range.
- Retry the command; TCM-committed changes are durable and the second round is safe to repeat.
- Inspect the wrapped IOException cause for connection-level details.
Example fix
// before nodetool adminconsensusmigration finish ks # node down mid-repair // after nodetool status # all nodes Up nodetool adminconsensusmigration finish ks # safe to re-run
Defensive patterns
Strategy: retry
Validate before calling
// preflight: all nodes Up and JMX reachable
if (!allNodesUp(probe)) throw new IllegalStateException("Cannot finish migration with nodes down"); Try / catch
try {
probe.startAndBlockOnAsyncRepairs(out, repairCmds);
}
catch (IOException e) {
log("Migration finish failed for " + keyspaces + "; TCM changes are durable — safe to re-run after nodes recover");
retryWithBackoff(() -> probe.startAndBlockOnAsyncRepairs(out, repairCmds));
} Prevention
- Verify nodetool status shows all nodes Up before finishing migration.
- Allow generous JMX timeouts — blocking on repairs can be long-running.
- Re-run the finish command after transient failures; the second round is idempotent.
- Monitor repair progress and migration state via protocol change logs.
When it happens
Trigger: Running `nodetool adminconsensusmigration finish`-style migration completion when the JMX connection drops, repair coordination fails, or a targeted node is down during startAndBlockOnAsyncRepairs.
Common situations: Node loss during migration repair; JMX timeouts because repairs take longer than the connection tolerates; ranges computed from an outdated ring after topology change.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- Error occurred during repair
- Argument must have keyspace and table values.
- Cannot set concurrent_validations greater than…
- Error during clearing snapshots
- Error during moving node
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/ffdcba87a7d440b4.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/tools/nodetool/ConsensusMigrationAdmin.java:174
List<RepairCmd> repairCmds = new ArrayList<>(keyspaceNames.size() * 2);
// Finish can't actually finish with one set of repairs when migrating from Paxos -> Accord
// and it's async when the next invocation will see TCM updates from the repair that will correctly determine
// the next set of repairs needed. If we spin we will issue redundant repairs.
// It's also pretty involved not to return handles on the repairs since there is already a lot of plumbing
// leveraging monitoring in progress repairs.
output.out.println("Starting first round of repairs");
for (String keyspace : keyspaceNames)
{
repairCmds.add(new FinishMigrationRepairCommand(probe, keyspace, maybeTableNames, maybeRangesStr, ConsensusMigrationTarget.paxos));
repairCmds.add(new FinishMigrationRepairCommand(probe, keyspace, maybeTableNames, maybeRangesStr, ConsensusMigrationTarget.accord));
}
try
{
probe.startAndBlockOnAsyncRepairs(probe.output().out, repairCmds);
}
catch (IOException e)
{
throw new RuntimeException("Error occurred attempting to finish migration for keyspace(s) " + keyspaceNames + " tables " + maybeTableNames + " and ranges " + maybeRangesStr, e);
}
// The repair should have at least committed the TCM change to the node we asked to coordinate the repair
// so calling finishedConsensusMigration a second time should trigger any needed 2nd phase repairs
// or does nothing if none are needed
output.out.println("Starting second round of repairs (may do nothing if migrating from Accord to Paxos)");
repairCmds.clear();
for (String keyspace : keyspaceNames)
{
repairCmds.add(new FinishMigrationRepairCommand(probe, keyspace, maybeTableNames, maybeRangesStr, ConsensusMigrationTarget.accord));
}
try
{
probe.startAndBlockOnAsyncRepairs(probe.output().out, repairCmds);
}
catch (IOException e)
{
throw new RuntimeException("Error occurred attempting to finish migration for keyspace(s) " + keyspaceNames + " tables " + maybeTableNames + " and ranges " + maybeRangesStr, e);
}View on GitHub (pinned to 88fd0f6a0e)