apache/cassandra · error · IllegalStateException
Can not resume bootstrap as join sequence has not been start
Error message
Can not resume bootstrap as join sequence has not been started
What it means
Thrown by StorageService.resumeBootstrap when the node's current in-progress sequence in ClusterMetadata is neither a BootstrapAndJoin nor a BootstrapAndReplace. It means resumeBootstrap was invoked, but no bootstrap/join sequence was ever started (or it already finished and was cleaned up), so there is nothing to resume. Cassandra requires an actual in-flight multi-step operation persisted in ClusterMetadata before a bootstrap can be resumed.
Source
Thrown at src/java/org/apache/cassandra/service/StorageService.java:1038
throw new IllegalStateException("Cannot join the ring until bootstrap completes");
}
}
else if (isBootstrapMode())
{
// bootstrap is not complete hence node cannot join the ring
logger.warn("Can't join the ring because bootstrap hasn't completed.");
throw new IllegalStateException("Cannot join the ring until bootstrap completes");
}
}
public void resumeBootstrapSequence()
{
ClusterMetadata metadata = ClusterMetadata.current();
NodeId id = metadata.myNodeId();
MultiStepOperation<?> sequence = metadata.inProgressSequences.get(id);
if (!(sequence instanceof BootstrapAndJoin) && !(sequence instanceof BootstrapAndReplace))
throw new IllegalStateException("Can not resume bootstrap as join sequence has not been started");
clearOngoingBootstrap();
InProgressSequences.finishInProgressSequences(id);
// only start transports and report that we're done if the resumed bootstrap completed successfully
// See CASSANDRA-16491
if (ongoingBootstrap.get() == null)
{
if (!isNativeTransportRunning())
daemon.initializeClientTransports();
daemon.start();
progressSupport.progress("bootstrap", new ProgressEvent(ProgressEventType.COMPLETE, 1, 1, "Resume bootstrap complete"));
logger.info("Resume complete");
}
}
public boolean readyToFinishJoiningRing()
{
ClusterMetadata metadata = ClusterMetadata.current();
NodeId id = metadata.myNodeId();View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Verify the node actually has an in-flight bootstrap: check nodetool metadata / logs for a BootstrapAndJoin or BootstrapAndReplace sequence before calling resumebootstrap
- If bootstrap never started, just start the node normally (or run the bootstrap/replacement again) instead of resuming
- If the sequence is stuck in a bad state, cancel it (nodetool cancelhandoff / cancel the bootstrap per docs) and re-bootstrap from scratch
- If bootstrap already completed, no action is needed — the node is already joined; skip the resume step
Example fix
// before: blindly resuming
storageService.resumeBootstrap();
// after: only resume when a bootstrap sequence exists
ClusterMetadata md = ClusterMetadata.current();
MultiStepOperation<?> seq = md.inProgressSequences.get(md.myNodeId());
if (seq instanceof BootstrapAndJoin || seq instanceof BootstrapAndReplace)
storageService.resumeBootstrap(); Defensive patterns
Strategy: validation
Validate before calling
ClusterMetadata md = ClusterMetadata.current();
MultiStepOperation<?> seq = md.inProgressSequences.get(md.myNodeId());
boolean canResume = seq instanceof BootstrapAndJoin || seq instanceof BootstrapAndReplace;
if (!canResume) throw new IllegalStateException("No bootstrap sequence in progress; start bootstrap instead of resuming"); Type guard
static boolean isBootstrapSequence(MultiStepOperation<?> seq) {
return seq instanceof BootstrapAndJoin || seq instanceof BootstrapAndReplace;
} Try / catch
try {
storageService.resumeBootstrap();
} catch (IllegalStateException e) {
if (e.getMessage().contains("join sequence has not been started")) {
logger.warn("Nothing to resume; node is not mid-bootstrap", e);
} else throw e;
} Prevention
- Check nodetool metadata / logs for an in-progress bootstrap sequence before calling resumebootstrap
- Only use resumebootstrap after an interrupted bootstrap, not as a general join command
- Automate the check: gate resume calls on the presence of BootstrapAndJoin/BootstrapAndReplace in ClusterMetadata
When it happens
Trigger: Calling nodetool resumebootstrap (or StorageService.resumeBootstrap()) on a node whose ClusterMetadata.inProgressSequences contains no BootstrapAndJoin/BootstrapAndReplace entry for its own NodeId — e.g. the node never started bootstrapping, bootstrap already completed, the sequence was cancelled, or the node was restarted after the sequence was removed.
Common situations: Operator runs resumebootstrap on a node that isn't actually stuck mid-bootstrap; running it on an already-bootstrapped node by mistake; running it after a failed bootstrap was cancelled and cleaned up; cluster metadata was reset or the node was decommissioned/re-added.
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 finish joining ring as join sequence has not been st
- 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/3f6a1ee8ebbcaec4.
Report an issue: GitHub.