apache/cassandra · error · java.lang.UnsupportedOperationException

This node has more than one token and cannot be moved thusly

Error message

This node has more than one token and cannot be moved thusly.

What it means

move(Token) only supports single-token (non-vnode) nodes. If the local node currently owns more than one token, moving 'the' token is ambiguous, so UnsupportedOperationException is thrown after logging the invalid request.

Source

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

    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,
                                                                 Collections.singleton(newToken),
                                                                 ClusterMetadataService.instance().placementProvider(),
                                                                 true),
                                                 m -> m,
                                                 failureHandler("PrepareMove", StorageService.instance::markMoveFailed));
        InProgressSequences.finishInProgressSequences(self);

        if (logger.isDebugEnabled())
            logger.debug("Successfully moved to new token {}", StorageService.instance.getLocalTokens().iterator().next());
    }

    private static ClusterMetadataService.CommitFailureHandler<ClusterMetadata> failureHandler(String type, Runnable markFailed)
    {
        return (code, msg) -> {
            logger.warn("Got failure committing {} transformation: {} {}", type, code, msg);

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Do not use move on vnode nodes; rebalance by decommissioning and re-bootstrapping with adjusted initial tokens, or use a rebalancing tool.
  2. If single-token operation is truly required, redeploy the node with num_tokens=1 and a chosen initial_token.
  3. Use `nodetool cleanup` after ownership changes rather than trying to move tokens.

Example fix

// before
nodetool move <token>                    // fails on vnode node
// after
nodetool decommission && rebootstrap with desired initial_token (or manage vnodes via num_tokens)
Defensive patterns

Strategy: validation

Validate before calling

if (ClusterMetadata.current().tokenMap.tokens(self).size() > 1)
    throw new UnsupportedOperationException("move is not supported for vnode nodes");

Type guard

boolean isSingleTokenNode(NodeId self) { return ClusterMetadata.current().tokenMap.tokens(self).size() == 1; }

Try / catch

try { move(token); }
catch (UnsupportedOperationException e) { if (e.getMessage().contains("more than one token")) { rebalanceViaBootstrap(); } else throw e; }

Prevention

When it happens

Trigger: Calling `nodetool move` on a node configured with num_tokens > 1 (vnodes) - metadata.tokenMap.tokens(self).size() > 1 - so the single-target move cannot be expressed.

Common situations: Operators accustomed to old single-token clusters running move on modern vnode-enabled nodes; attempting to rebalance a vnode node with nodetool move instead of cleanup/decommission+rebootstrap.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/ca1a94497c9c2812. Report an issue: GitHub.