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
- Do not use move on vnode nodes; rebalance by decommissioning and re-bootstrapping with adjusted initial tokens, or use a rebalancing tool.
- If single-token operation is truly required, redeploy the node with num_tokens=1 and a chosen initial_token.
- 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
- Only use nodetool move on num_tokens=1 nodes
- Rebalance vnode clusters via decommission/rebootstrap or tooling
- Document vnode topology procedures for operators
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
- Cannot return topology when accord.enabled = false in cassan
- Chunk cache size cannot be changed.
- %s
- Compressor does not support dictionary training: <compressor
- This table currently does not support the complex partial pa
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/ca1a94497c9c2812.
Report an issue: GitHub.