apache/cassandra · error · UnsupportedOperationException

Node in state; wait for status to become normal

Error message

Node in  state; wait for status to become normal

What it means

decommission checks StorageService.instance.operationMode() and only permits LEAVING, NORMAL, or DECOMMISSION_FAILED. If the node is in any other mode (e.g. BOOTSTRAP, JOINING, STARTING, or mid-rebuild), it throws this UnsupportedOperationException. The message interpolates the current mode.

Source

Thrown at src/java/org/apache/cassandra/tcm/sequences/SingleNodeSequences.java:75

    Logger logger = LoggerFactory.getLogger(SingleNodeSequences.class);

    /**
     * Entrypoint to begin node decommission process.
     *
     * @param shutdownNetworking if set to true, will also shut down networking on completion
     * @param force if set to true, will decommission the node even if this would mean there will be not enough nodes
     *              to satisfy replication factor
     */
    static void decommission(boolean shutdownNetworking, boolean force)
    {
        if (ClusterMetadataService.instance().isMigrating() || ClusterMetadataService.state() == ClusterMetadataService.State.GOSSIP)
            throw new IllegalStateException("This cluster is migrating to cluster metadata, can't decommission until that is done.");

        ClusterMetadata metadata = ClusterMetadata.current();

        StorageService.Mode mode = StorageService.instance.operationMode();
        if (!EnumSet.of(LEAVING, NORMAL, DECOMMISSION_FAILED).contains(mode))
            throw new UnsupportedOperationException("Node in " + mode + " state; wait for status to become normal");
        logger.debug("DECOMMISSIONING");

        NodeId self = metadata.myNodeId();
        Collection<Token> tokens = metadata.tokenMap.tokens(self);
        ReconfigureCMS.maybeReconfigureCMS(metadata, getBroadcastAddressAndPort());
        MultiStepOperation<?> inProgress = metadata.inProgressSequences.get(self);

        if (inProgress == null)
        {
            logger.info("starting decommission with {} {}", metadata.epoch, self);
            // We reset transferred ranges upon starting a decommission so that we fully stream
            // anything written since a previous attempt which may not have been persisted to a pending endpoint
            SystemKeyspace.resetTransferredRanges();
            logger.info("done resetting transferred ranges {} {}", metadata.epoch, self);
            ClusterMetadataService.instance().commit(new PrepareLeave(self,
                                                                      force,
                                                                      ClusterMetadataService.instance().placementProvider(),
                                                                      LeaveStreams.Kind.UNBOOTSTRAP),

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Wait until `nodetool status` / logs show the node is in NORMAL state, then retry decommission.
  2. If stuck in DECOMMISSION_FAILED, decommission is allowed — retry it to resume/finish.
  3. If a join/bootstrap is genuinely in progress, complete or abort it first.
  4. After a crash, restart the node so it settles into NORMAL before decommissioning.

Example fix

// before
nodetool decommission  // node still JOINING
// after
// guard before calling
if (StorageService.instance.operationMode() == StorageService.Mode.NORMAL) {
    nodetool.decommission();
}
Defensive patterns

Strategy: validation

Validate before calling

StorageService.Mode mode = StorageService.instance.operationMode();
if (!EnumSet.of(Mode.LEAVING, Mode.NORMAL, Mode.DECOMMISSION_FAILED).contains(mode)) {
    throw new RuntimeException("Node in " + mode + " state; decommission not allowed yet");
}

Try / catch

try {
    decommission();
} catch (UnsupportedOperationException e) {
    if (e.getMessage().startsWith("Node in ") && e.getMessage().contains("wait for status")) {
        waitForMode(StorageService.Mode.NORMAL);
        decommission();
    } else throw e;
}

Prevention

When it happens

Trigger: Calling decommission while the node's operation mode is not NORMAL/LEAVING/DECOMMISSION_FAILED — e.g. the node is still joining, bootstrapping, or recovering from a failed decommission in another state.

Common situations: Operator runs decommission too soon after node start before status is NORMAL; a previous bootstrap or join is still in flight; a stuck prior operation left the node in a non-normal mode.

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/227427abb4af077e. Report an issue: GitHub.