apache/cassandra · error · RuntimeException

Could not perform next step of joining the ring %s, restart

Error message

Could not perform next step of joining the ring %s, restart this node and inflight operations will attempt to complete. If no progress is made, cancel the join process for this node and retry

What it means

Thrown by StorageService.finishJoiningRing after executing the MID_JOIN/MID_REPLACE step of the temporary finishJoining copy of the sequence: if executeNext() does not return a continuable result, the join could not advance and the RuntimeException is thrown naming the step that failed. This indicates the cluster could not apply the transformation needed to finish joining, and the operator must let in-flight operations retry or cancel the join.

Source

Thrown at src/java/org/apache/cassandra/service/StorageService.java:1119

                                            "If no progress is made, cancel the join process for this node and retry");
        }

        if (sequence.kind() == MultiStepOperation.Kind.REPLACE && sequence.nextStep() != Transformation.Kind.MID_REPLACE)
            throw new IllegalStateException("Can not finish joining ring, sequence is in an incorrect state. " +
                                            "If no progress is made, cancel the join process for this node and retry");

        // Create a temporary new copy of the sequence with the finishJoining flag set to true and with streaming
        // disabled, then execute its next step (the MID_*). We do this because effectively we want to jump over the
        // MID_JOIN/MID_REPLACE of the "real" sequence. Note, this does not replace the existing sequence in
        // ClusterMetadata with the temporary copy, but an effect of executing the MID step of the copy is that it will
        // update the persisted state of the sequence leaving it with only the FINISH_* step to complete.
        Transformation.Kind next = sequence.nextStep();
        boolean success = (sequence instanceof BootstrapAndJoin)
                          ? ((BootstrapAndJoin)sequence).finishJoiningRing().executeNext().isContinuable()
                          : ((BootstrapAndReplace)sequence).finishJoiningRing().executeNext().isContinuable();

        if (!success)
            throw new RuntimeException(String.format("Could not perform next step of joining the ring %s, " +
                                                     "restart this node and inflight operations will attempt to complete. " +
                                                     "If no progress is made, cancel the join process for this node and retry",
                                                     next));

        // Now the MID step has completed and updated the sequence persisted in ClusterMetadata, finish it.
        InProgressSequences.finishInProgressSequences(id);
    }

    void doAuthSetup()
    {
        doAuthSetup(true);
    }

    @VisibleForTesting
    public void doAuthSetup(boolean async)
    {
        if (!authSetupCalled.getAndSet(true))
        {

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Restart this node — in-flight operations will automatically attempt to complete the join on startup
  2. Check cluster connectivity and that all nodes are up (nodetool status) so transformations can be committed
  3. If no progress is made after restarts, cancel the join process for this node (cancelhandoff / cancel bootstrap) and retry the join from scratch
  4. Inspect logs on this node and the cluster-metadata coordinator for why the MID step transformation failed
Defensive patterns

Strategy: retry

Validate before calling

Transformation.Kind next = sequence.nextStep();
// ensure cluster is healthy before executing the MID step
boolean clusterHealthy = StreamSupport.stream(ClusterMetadata.current().dir().members.spliterator(), false)
    .allMatch(node -> failureDetector.isAlive(node));
if (!clusterHealthy) throw new IllegalStateException("Cluster not fully alive; postpone finishing join of step " + next);

Try / catch

try {
    storageService.finishJoiningRing();
} catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Could not perform next step of joining the ring")) {
        logger.warn("MID step " + e.getMessage() + " failed; restarting node so in-flight ops retry", e);
        // schedule restart or retry with backoff
    } else throw e;
}

Prevention

When it happens

Trigger: finishJoiningRing executed the MID_JOIN (BootstrapAndJoin) or MID_REPLACE (BootstrapAndReplace) step but the resulting transformation was not applied successfully (executeNext().isContinuable() == false) — e.g. another node rejected the transformation, cluster metadata moved on, or a concurrent operation conflicts.

Common situations: Concurrent topology operations conflicting with the join; the coordinator node for the transformation is down or unreachable; the persisted sequence in ClusterMetadata changed between the check and the execution; network partition during finishjoin.

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


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/7a57454d80bb6448. Report an issue: GitHub.