apache/cassandra · error · IllegalStateException
Can not finish joining ring as join sequence has not been st
Error message
Can not finish joining ring as join sequence has not been started
What it means
Thrown by StorageService.finishJoiningRing when the node's in-progress sequence kind is neither JOIN nor REPLACE, meaning no join/replace sequence was started even though the operator asked to finish joining the ring. This is the double-check of the conditions verified earlier in readyToFinishJoiningRing. It prevents finishing a join that does not exist in ClusterMetadata.
Source
Thrown at src/java/org/apache/cassandra/service/StorageService.java:1095
* At the point when an operator decides to bring the node out of write survey mode, we need to execute the
* remaining steps of the join/replace sequence. The caveat is that although this execution will recommence at the
* point it left off (after the START_JOIN/START_REPLACE step), the {@code finishJoiningRing} flag which causes
* execution to pause for write survey mode must be overridden, so that we fully execute the MID step. We also want
* force the {@code streamData} flag to false, to prevent re-streaming the bootstrap data. To do this, we create a
* temporary copy of the {@link MultiStepOperation} and manually execute its next step after verifying expected
* invariants. This causes the MID step to fully execute, which then moves the sequence persisted in
* {@link ClusterMetadata}'s in-progress sequences onto the FINISH step, and we can complete the operation in the
* normal way with {@link InProgressSequences#finishInProgressSequences(MultiStepOperation.SequenceKey)}
* */
private void exitWriteSurveyMode()
{
ClusterMetadata metadata = ClusterMetadata.current();
NodeId id = metadata.myNodeId();
MultiStepOperation<?> sequence = metadata.inProgressSequences.get(id);
// Double check the conditions we verified in readyToFinishJoiningRing
if (sequence.kind() != MultiStepOperation.Kind.JOIN && sequence.kind() != MultiStepOperation.Kind.REPLACE)
throw new IllegalStateException("Can not finish joining ring as join sequence has not been started");
if ((sequence.kind() == MultiStepOperation.Kind.JOIN && sequence.nextStep() != Transformation.Kind.MID_JOIN)
|| (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");
}
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();View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Confirm with nodetool metadata (or logs) that a JOIN or REPLACE sequence is actually in progress for this node
- If no join exists, bootstrap/join the node normally instead of calling finishjoin
- If the join already completed, no action needed — the node is a ring member
- If the wrong operation is in progress, cancel it and restart the intended join process
Defensive patterns
Strategy: validation
Validate before calling
MultiStepOperation<?> seq = ClusterMetadata.current().inProgressSequences.get(id);
boolean canFinish = seq != null && (seq.kind() == MultiStepOperation.Kind.JOIN || seq.kind() == MultiStepOperation.Kind.REPLACE);
if (!canFinish) throw new IllegalStateException("No JOIN/REPLACE sequence in progress; cannot finish joining ring"); Type guard
static boolean isJoinOrReplace(MultiStepOperation<?> seq) {
return seq != null && (seq.kind() == MultiStepOperation.Kind.JOIN || seq.kind() == MultiStepOperation.Kind.REPLACE);
} Try / catch
try {
storageService.finishJoiningRing();
} catch (IllegalStateException e) {
if (e.getMessage().contains("join sequence has not been started")) {
logger.warn("No join/replace sequence in progress; nothing to finish", e);
} else throw e;
} Prevention
- Verify a JOIN or REPLACE sequence is in progress (nodetool metadata) before running finishjoin
- Don't confuse finishjoin with resumebootstrap — check which command matches the node's actual state
- After a completed join, skip finishjoin entirely
When it happens
Trigger: Calling nodetool finishjoin / finishJoiningRing when metadata.inProgressSequences for this node holds a sequence whose kind() is not MultiStepOperation.Kind.JOIN or Kind.REPLACE — e.g. no sequence at all, or an unrelated sequence (bootstrap-only, decommission, rebuild).
Common situations: Running finishjoin on a node that was never bootstrapped into the ring; running it after the join already finished; running it on a node executing a different multi-step operation; confusion between resumebootstrap and finishjoin commands.
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
- Can not resume bootstrap as join sequence has not been start
- Can not finish joining ring, sequence is in an incorrect sta
- Could not perform next step of joining the ring %s, restart
- Can't join the ring because in write_survey mode and bootstr
- Can't join the ring because bootstrap hasn't completed.
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/e58d7e42a1cfe213.
Report an issue: GitHub.