apache/cassandra · error · java.lang.UnsupportedOperationException

Can not remove a node that has an in-progress sequence

Error message

Can not remove a node that has an in-progress sequence

What it means

SingleNodeSequences.removeNode refuses to remove a node while ClusterMetadata still records an in-progress multi-step sequence (leave/move/decommission/remove) for that node. Thrown as UnsupportedOperationException because concurrent topology operations on the same node are not supported; the previous operation must be finished or aborted first.

Source

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

    static void removeNode(NodeId toRemove, boolean force)
    {
        ClusterMetadata metadata = ClusterMetadata.current();
        if (toRemove.equals(metadata.myNodeId()))
            throw new UnsupportedOperationException("Cannot remove self");
        InetAddressAndPort endpoint = metadata.directory.endpoint(toRemove);
        if (endpoint == null)
            throw new UnsupportedOperationException("Host ID not found.");
        if (Gossiper.instance.getLiveMembers().contains(endpoint))
            throw new UnsupportedOperationException("Node " + endpoint + " is alive and owns this ID. Use decommission command to remove it from the ring");

        NodeState removeState = metadata.directory.peerState(toRemove);
        if (removeState == null)
            throw new UnsupportedOperationException("Node to be removed is not a member of the token ring");
        if (removeState == NodeState.LEAVING)
            logger.warn("Node {} is already leaving or being removed, continuing removal anyway", endpoint);

        if (metadata.inProgressSequences.contains(toRemove))
            throw new UnsupportedOperationException("Can not remove a node that has an in-progress sequence");

        ReconfigureCMS.maybeReconfigureCMS(metadata, endpoint);

        logger.info("starting removenode with {} {}", metadata.epoch, toRemove);
        Collection<Token> tokens  = metadata.tokenMap.tokens(toRemove);
        ClusterMetadataService.instance().commit(new PrepareLeave(toRemove,
                                                                  force,
                                                                  ClusterMetadataService.instance().placementProvider(),
                                                                  LeaveStreams.Kind.REMOVENODE));
        InProgressSequences.finishInProgressSequences(toRemove);
        Gossiper.instance.unsafeBroadcastLeftStatus(endpoint, tokens, metadata.directory.allJoinedEndpoints());
    }

    static void abortRemoveNode(String nodeId)
    {
        abortHelper(nodeId, MultiStepOperation.Kind.REMOVE, null);
    }

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Wait for or complete the in-progress sequence (resume/finish the decommission/move) before removing the node.
  2. Abort the in-progress sequence first, e.g. `nodetool abortdecommission`, `nodetool abortremovenode`, or the matching abort command, then retry removenode.
  3. Inspect `nodetool inprogresssequences` / ClusterMetadata.inProgressSequences to confirm the node and sequence kind, then choose resume vs abort.
  4. As a last resort after cluster recovery, verify the sequence is truly stale and clear it via the supported recovery path before re-running removenode.

Example fix

// before
nodetool removenode <hostId>            // throws: Can not remove a node that has an in-progress sequence
// after
nodetool abortremovenode <hostId>       # or abortdecommission / resume the operation
nodetool removenode <hostId>
Defensive patterns

Strategy: validation

Validate before calling

ClusterMetadata md = ClusterMetadata.current();
if (md.inProgressSequences.contains(toRemove))
    throw new IllegalStateException("defer removenode: sequence in progress for " + toRemove);

Try / catch

try { SingleNodeSequences.removeNode(id, force); }
catch (UnsupportedOperationException e) { /* sequence in progress - resume/abort first, then retry */ }

Prevention

When it happens

Trigger: Calling `nodetool removenode <hostId>` (which invokes removeNode) while the target node still appears in metadata.inProgressSequences - e.g. a prior decommission, move, or removenode was started but not completed or aborted.

Common situations: Operators retry a failed removenode/decommission without first aborting it; a node crashed mid-decommission leaving the sequence registered; scripted topology changes overlap (move then immediate remove).

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/1a0ff63bc059e3a5. Report an issue: GitHub.