apache/cassandra · error · java.lang.IllegalArgumentException

Error: Can not sort by token when there is not token per…

Error message

Error: Can not sort by token when there is not token per node.

What it means

nodetool status supports sorting by token only when the cluster has exactly one token per node (vnodes disabled). With virtual nodes a node owns many tokens, so token ordering is undefined; Status.execute() prints the message to stderr and throws IllegalArgumentException.

Solutions

  1. Drop the -t/--sort token option and sort by another field (id, address, load, own).
  2. Set num_tokens=1 per node if single-token-per-node is truly required (requires migration planning).
  3. Use a tool that can represent vnodes if token-ordered output is essential.

Example fix

// before
nodetool status -t
// after
nodetool status -l
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check before requesting token sort
if (numTokensPerNode > 1 && requestedSort == SortBy.token) throw new IllegalArgumentException('Cannot sort by token with vnodes');

Try / catch

try { runStatus(args); } catch (IllegalArgumentException e) { if (e.getMessage().contains("Can not sort by token")) { retryWithoutTokenSort(); } else throw e; }

Prevention

When it happens

Trigger: Running `nodetool status -t token` (or `nodetool status <keyspace> -t`) on a cluster configured with num_tokens > 1.

Common situations: Running the sort-by-token option against modern default configurations where num_tokens defaults to 16, i.e. multi-token nodes.

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/381b4281f03017ab. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/tools/nodetool/Status.java:149

        SortedMap<String, SetHostStatWithPort> dcs = CommandUtils.getOwnershipByDcWithPort(probe, resolveIp, tokensToEndpoints, ownerships);

        int nodesOfTokens = tokensToEndpoints.values().size();

        // More tokens than nodes (aka vnodes)?
        if (hostIDMap.size() < nodesOfTokens)
            isTokenPerNode = false;

        if (sortBy == null)
        {
            if (isTokenPerNode)
                sortBy = SortBy.token;
            else
                sortBy = SortBy.id;
        }
        else if (!isTokenPerNode && sortBy == SortBy.token)
        {
            errOut.printf("%nError: Can not sort by token when there is not token per node.%n");
            throw new IllegalArgumentException("Error: Can not sort by token when there is not token per node.");
        }
        else if (!resolveIp && sortBy == SortBy.host)
        {
            errOut.printf("%nError: Can not sort by host when there is not -r/--resolve-ip flag used.%n");
            throw new IllegalArgumentException("Error: Can not sort by host when there is not -r/--resolve-ip flag used.");
        }

        // Datacenters
        for (Map.Entry<String, SetHostStatWithPort> dc : dcs.entrySet())
        {
            TableBuilder tableBuilder = sharedTable.next();
            addNodesHeader(hasEffectiveOwns, tableBuilder);

            ArrayListMultimap<InetAddressAndPort, HostStatWithPort> hostToTokens = ArrayListMultimap.create();
            for (HostStatWithPort stat : dc.getValue())
                hostToTokens.put(stat.endpointWithPort, stat);

            Map<String, List<Object>> data = new HashMap<>();

View on GitHub (pinned to 88fd0f6a0e)