apache/cassandra · error · java.lang.IllegalArgumentException
target token is already owned by another node.
Error message
target token %s is already owned by another node.
What it means
move checks ClusterMetadata.current().tokenMap.tokens() and throws IllegalArgumentException if the requested target token is already assigned to some node in the ring. Tokens must be unique; moving onto an owned token would corrupt ownership ranges.
Solutions
- Choose a token not present in the ring: run `nodetool ring` (or query ClusterMetadata.tokenMap) and pick an unowned token.
- If the token belongs to a stale/removed node, finish removing that node first (removenode), then retry.
- Use a load-balancing tool or omit the explicit token so a balanced unowned token is chosen automatically.
Example fix
// before ss.move(existingToken); // IllegalArgumentException // after Set<Token> owned = ClusterMetadata.current().tokenMap.tokens(); if (!owned.contains(newToken)) ss.move(newToken);
Defensive patterns
Strategy: validation
Validate before calling
if (ClusterMetadata.current().tokenMap.tokens().contains(newToken))
throw new IllegalArgumentException("token already owned: " + newToken); Try / catch
try { move(token); }
catch (IllegalArgumentException e) { if (e.getMessage().contains("already owned")) { pickUnownedToken(); } else throw e; } Prevention
- Refresh the ring view immediately before choosing a token
- Never hardcode tokens from stale snapshots
- Ensure removed nodes are fully removed before reusing their tokens
When it happens
Trigger: Running `nodetool move <token>` with a token that already exists in the ring - e.g. copying another node's token, reusing a token from a removed node that is still registered, or computing a token that collides with an existing one.
Common situations: Rebalancing scripts that hardcode tokens from a stale ring snapshot; attempting to move a node onto the token of a node removed earlier but still present in cluster metadata; initial_token reuse across nodes.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Can not commit transformation
- Can not remove a node that has an in-progress sequence
- Can't move to the undefined (null) token.
- Cannot return topology when accord.enabled = false in…
- Endpoints by dc differ
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/82908091d059ce63.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/tcm/sequences/SingleNodeSequences.java:178
{
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,
Collections.singleton(newToken),
ClusterMetadataService.instance().placementProvider(),
true),
m -> m,
failureHandler("PrepareMove", StorageService.instance::markMoveFailed));
InProgressSequences.finishInProgressSequences(self);View on GitHub (pinned to 88fd0f6a0e)