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

  1. 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).
  2. Check repair history / logs (`nodetool netstats`, system protocol logs) for the failing range.
  3. Retry the command; TCM-committed changes are durable and the second round is safe to repeat.
  4. 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

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


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)