apache/cassandra · error · java.lang.IllegalStateException

This cluster is migrating to cluster metadata, can't move un

Error message

This cluster is migrating to cluster metadata, can't move until that is done.

What it means

SingleNodeSequences.move rejects moving a token while the cluster is still migrating from gossip-based metadata to Cluster Metadata (TCM). During migration (isMigrating() true or state == GOSSIP) topology operations are blocked to avoid divergent metadata, so an IllegalStateException is thrown.

Source

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

                                                                  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);
    }

    /**
     * move the node to new token or find a new token to boot to according to load
     *
     * @param newToken new token to boot to, or if null, find balanced token to boot to
     */
    static void move(Token newToken)
    {
        if (ClusterMetadataService.instance().isMigrating() || ClusterMetadataService.state() == ClusterMetadataService.State.GOSSIP)
            throw new IllegalStateException("This cluster is migrating to cluster metadata, can't move until that is done.");

        if (newToken == null)
            throw new IllegalArgumentException("Can't move to the undefined (null) token.");

        if (ClusterMetadata.current().tokenMap.tokens().contains(newToken))
            throw new IllegalArgumentException(String.format("target token %s is already owned by another node.", newToken));

        // address of the current node
        ClusterMetadata metadata = ClusterMetadata.current();
        NodeId self = metadata.myNodeId();
        // This doesn't make any sense in a vnodes environment.
        if (metadata.tokenMap.tokens(self).size() > 1)
        {
            logger.error("Invalid request to move(Token); This node has more than one token and cannot be moved thusly.");
            throw new UnsupportedOperationException("This node has more than one token and cannot be moved thusly.");
        }

        ClusterMetadataService.instance().commit(new PrepareMove(self,

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Wait until the TCM migration completes (all nodes report ClusterMetadata state, not GOSSIP) and re-run the move.
  2. Check `nodetool clustermetadata` / logs to see which nodes have not completed migration and restart/upgrade them.
  3. If migration is stuck, resolve the underlying cause (down peer, failed bootstrap) per upgrade docs, then retry.
  4. Defer the token move until after the upgrade window; it is not allowed mid-migration.
Defensive patterns

Strategy: validation

Validate before calling

if (ClusterMetadataService.instance().isMigrating() || ClusterMetadataService.state() == ClusterMetadataService.State.GOSSIP)
    return; // defer move until migration completes

Try / catch

try { SingleNodeSequences.move(token); }
catch (IllegalStateException e) { if (e.getMessage().contains("migrating")) { scheduleRetryAfterMigration(); } else throw e; }

Prevention

When it happens

Trigger: Running `nodetool move <newToken>` while ClusterMetadataService.instance().isMigrating() is true or ClusterMetadataService.state() is State.GOSSIP - i.e. during or after a failed in-place upgrade to TCM before migration completes.

Common situations: Upgrading a cluster to the Cassandra TCM releases and issuing topology commands before migration finishes; a node still running in GOSSIP state after a rolling restart; migration stuck halfway due to a failed node.

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