{"record":{"id":"49d47d0f2cf15fac","repo":"apache/cassandra","slug":"this-node-has-more-than-one-token-and-cannot-be-mo-49d47d","errorCode":null,"errorMessage":"This node has more than one token and cannot be moved thusly.","messagePattern":"This node has more than one token and cannot be moved thusly\\.","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/tools/CMSOfflineTool.java","lineNumber":502,"sourceCode":"                ClusterMetadata updatedMetadata = finishInProgressSequence(nodeId, token, metadata);\n                writeMetadata(output, updatedMetadata, outputFilePath);\n                return;\n            }\n\n            if (null == token)\n            {\n                throw new IllegalArgumentException(\"Token required when no MOVE sequence is in progress.\");\n            }\n            metadata.partitioner.getTokenFactory().validate(token);\n            Token toToken = metadata.partitioner.getTokenFactory().fromString(token);\n            if (metadata.tokenMap.tokens().contains(toToken))\n            {\n                NodeId tokenOwnerId = metadata.tokenMap.owner(toToken);\n                throw new IllegalArgumentException(\"Target token \" + toToken + \" is already owned by node \" + tokenOwnerId.id());\n            }\n            if (metadata.tokenMap.tokens(nodeId).size() > 1)\n            {\n                throw new UnsupportedOperationException(\"This node has more than one token and cannot be moved thusly.\");\n            }\n\n            PrepareMove prepareMove = new PrepareMove(nodeId, Set.of(toToken), new UniformRangePlacement(), false);\n            ClusterMetadata updatedMetadata = prepareMove.execute(metadata).success().metadata;\n            updatedMetadata = updatedMetadata.inProgressSequences.get(nodeId).applyTo(updatedMetadata).success().metadata;\n            writeMetadata(output, updatedMetadata, outputFilePath);\n        }\n\n        ClusterMetadata finishInProgressSequence(NodeId nodeId, String token, ClusterMetadata metadata)\n        {\n            MultiStepOperation<?> multiStepOperation = metadata.inProgressSequences.get(nodeId);\n            if (multiStepOperation.kind() != MultiStepOperation.Kind.MOVE)\n            {\n                throw new IllegalArgumentException(\"Another sequence of kind \" + multiStepOperation.kind() +\n                                                   \" is in progress for node \" + nodeIdentifierOption.getNodeIpOrId() +\n                                                   \". Cannot proceed with move.\");\n            }\n","sourceCodeStart":484,"sourceCodeEnd":520,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tools/CMSOfflineTool.java#L484-L520","documentation":"MOVE (as issued here) relocates a node's single token, so it only works for nodes that own exactly one token. If metadata.tokenMap.tokens(nodeId).size() > 1 the tool throws this UnsupportedOperationException because multi-token nodes cannot be moved this way.","triggerScenarios":"Move subcommand in `execute` when the target node has more than one token assigned in metadata.tokenMap (e.g. vnodes configured with num_tokens > 1).","commonSituations":"Cluster was bootstrapped with vnodes; operator attempts `cms move` on such a node expecting it to work like a single-token cluster.","solutions":["Use a rebalancing workflow appropriate for vnodes (e.g. rebootstrap with desired num_tokens=1 or run a decommission/rejoin) instead of move.","Rebuild the node with num_tokens set to 1 and chosen tokens, then move if needed.","If single-token operation is required, migrate data off and re-add the node with one token."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (meta.tokenMap.tokens(nodeId).size() > 1)\n    throw new UnsupportedOperationException(\"Node \" + nodeId + \" has \" + meta.tokenMap.tokens(nodeId).size() + \" tokens; move requires a single-token node\");","typeGuard":null,"tryCatchPattern":"try { tool.move(nodeId, token); } catch (UnsupportedOperationException e) { if (e.getMessage().contains(\"more than one token\")) { useVnodeRebalanceFlow(); } else throw e; }","preventionTips":["Check the node's token count before attempting move.","Set num_tokens=1 for clusters that rely on explicit token moves.","Use decommission/bootstrap cycles for vnodes rebalancing."],"tags":["multiple-tokens","vnodes","move","unsupported-operation"],"backgroundTag":"unsupported-operation","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}