apache/cassandra · error · IllegalArgumentException
Target token is already owned by node
Error message
Target token ${toToken} is already owned by node ${tokenOwnerId} What it means
When starting a new MOVE, the target token must not already be assigned to another node in metadata.tokenMap. If tokenMap.tokens() contains toToken, the tool throws this IllegalArgumentException naming the current owner, since moving the node there would create a duplicate token ownership.
Solutions
- Pick an unowned token (e.g. a value not present in `nodetool ring` output) and re-run with that --token.
- If the token belongs to a decommissioned node, first remove that node's leftover token/state from the ring.
- Compute a balanced token assignment before moving to avoid collisions.
Example fix
// before bin/cms move -ip 10.0.0.5 --token 1234 // owned by node 2 // after bin/cms move -ip 10.0.0.5 --token 9876543210 // unowned token
Defensive patterns
Strategy: validation
Validate before calling
Token toToken = meta.partitioner.getTokenFactory().fromString(token);
if (meta.tokenMap.tokens().contains(toToken))
throw new IllegalArgumentException("Token " + token + " already owned by " + meta.tokenMap.owner(toToken)); Try / catch
try { tool.move(nodeId, token); } catch (IllegalArgumentException e) { if (e.getMessage().contains("already owned by node")) { pickUnownedTokenAndRetry(); } else throw e; } Prevention
- Check `nodetool ring` / tokenMap for token ownership before choosing a target token.
- Generate tokens from a balanced assignment rather than reusing old values.
- Never reuse tokens of nodes that were recently removed until their state is fully cleaned.
When it happens
Trigger: Move subcommand in `execute` with a --token value that metadata.tokenMap.owner(toToken) shows is already owned by a different node.
Common situations: Operator copies a token from another node's output or reuses a token from a decommissioned node whose entry still exists; token collision after manual token assignment.
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
- All nodes are not yet upgraded
- Another sequence of kind
- Another sequence of kind
- Can not add a new in-progress sequence for
- Can not commit transformation
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/13532ad19413f163.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/tools/CMSOfflineTool.java:498
NodeId nodeId = nodeIdentifierOption.getNodeId(metadata);
if (metadata.inProgressSequences.contains(nodeId))
{
ClusterMetadata updatedMetadata = finishInProgressSequence(nodeId, token, metadata);
writeMetadata(output, updatedMetadata, outputFilePath);
return;
}
if (null == token)
{
throw new IllegalArgumentException("Token required when no MOVE sequence is in progress.");
}
metadata.partitioner.getTokenFactory().validate(token);
Token toToken = metadata.partitioner.getTokenFactory().fromString(token);
if (metadata.tokenMap.tokens().contains(toToken))
{
NodeId tokenOwnerId = metadata.tokenMap.owner(toToken);
throw new IllegalArgumentException("Target token " + toToken + " is already owned by node " + tokenOwnerId.id());
}
if (metadata.tokenMap.tokens(nodeId).size() > 1)
{
throw new UnsupportedOperationException("This node has more than one token and cannot be moved thusly.");
}
PrepareMove prepareMove = new PrepareMove(nodeId, Set.of(toToken), new UniformRangePlacement(), false);
ClusterMetadata updatedMetadata = prepareMove.execute(metadata).success().metadata;
updatedMetadata = updatedMetadata.inProgressSequences.get(nodeId).applyTo(updatedMetadata).success().metadata;
writeMetadata(output, updatedMetadata, outputFilePath);
}
ClusterMetadata finishInProgressSequence(NodeId nodeId, String token, ClusterMetadata metadata)
{
MultiStepOperation<?> multiStepOperation = metadata.inProgressSequences.get(nodeId);
if (multiStepOperation.kind() != MultiStepOperation.Kind.MOVE)
{
throw new IllegalArgumentException("Another sequence of kind " + multiStepOperation.kind() +View on GitHub (pinned to 88fd0f6a0e)