{"record":{"id":"47c84d5585ae296d","repo":"apache/cassandra","slug":"could-not-find-range-for-token-in-replicagroups","errorCode":null,"errorMessage":"Could not find range for token  in ReplicaGroups: ","messagePattern":"Could not find range for token  in ReplicaGroups: ","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/tcm/ownership/ReplicaGroups.java","lineNumber":162,"sourceCode":"        Epoch lastModified = Epoch.EMPTY;\n        // find a range containing the *right* token for the given range - Range is start exclusive so if we looked for the\n        // left one we could get the wrong range\n        int pos = ordering.binarySearchAsymmetric(ranges, range.right, AsymmetricOrdering.Op.CEIL);\n        if (pos >= 0 && pos < ranges.size() && ranges.get(pos).contains(range))\n        {\n            VersionedEndpoints.ForRange eps = endpoints.get(pos);\n            lastModified = eps.lastModified();\n            builder.addAll(eps.get(), ReplicaCollection.Builder.Conflict.ALL);\n        }\n        return VersionedEndpoints.forRange(lastModified, builder.build());\n    }\n\n    public VersionedEndpoints.ForRange forRange(Token token)\n    {\n        int pos = ordering.binarySearchAsymmetric(ranges, token, AsymmetricOrdering.Op.CEIL);\n        if (pos >= 0 && pos < endpoints.size())\n            return endpoints.get(pos);\n        throw new IllegalStateException(\"Could not find range for token \" + token + \" in ReplicaGroups: \" + this);\n    }\n\n    public VersionedEndpoints.ForToken forToken(Token token)\n    {\n        return forRange(token).forToken(token);\n    }\n\n    public Delta difference(NodeIdLookup idLookup, ReplicaGroups next)\n    {\n        Multimap<NodeId, ReplicaNode> oldMap = this.byNodeId(idLookup);\n        Multimap<NodeId, ReplicaNode> newMap = next.byNodeId(idLookup);\n        return new NodeIdDelta(diff(oldMap, newMap), diff(newMap, oldMap));\n    }\n\n    private Multimap<NodeId, ReplicaNode> byNodeId(NodeIdLookup idLookup)\n    {\n        ImmutableMultimap.Builder<NodeId, ReplicaNode> builder = ImmutableMultimap.builder();\n        for (int i = 0; i < endpoints.size(); i++)","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/tcm/ownership/ReplicaGroups.java#L144-L180","documentation":"ReplicaGroups.forRange looks up the placement group owning a given token via a CEIL binary search over the sorted ranges. It throws IllegalStateException when the binary search fails to land on an existing range entry, i.e. the token lies outside every range this ReplicaGroups object covers, or its internal index is inconsistent.","triggerScenarios":"Calling forRange(token) or forToken(token) with a token that is not covered by any range in the ReplicaGroups object; commonly happens during token movement/bootstrap when placement metadata is stale or when querying a token outside the ring ranges known to this node.","commonSituations":"A node requests ownership for a token that was just added or removed but its local TCM metadata has not caught up; a bootstrap/replace plan computes ranges over an outdated ClusterMetadata snapshot; splitRangesForPlacement input validation was bypassed with tokens outside placement bounds.","solutions":["Refresh ClusterMetadata (via TCM) so the local ReplicaGroups reflects the current placement before calling forRange/forToken","Verify the token actually belongs to one of the ranges in the ReplicaGroups instance (e.g. check ranges.first/last bounds) before querying","If this occurs during bootstrap/decommission, re-run the placement computation so ranges are split for all new tokens first","Check for version skew: restart nodes or ensure all nodes see the same metadata epoch"],"exampleFix":"// before\nVersionedEndpoints.ForRange endpoints = metadata.placements().forToken(token);\n// after\nif (metadata.placements().asMap().keySet().stream().noneMatch(r -> r.contains(token)))\n    throw new IllegalArgumentException(\"token not covered by placements: \" + token);\nVersionedEndpoints.ForRange endpoints = metadata.placements().forToken(token);","handlingStrategy":"validation","validationCode":"boolean covered = metadata.placements().asMap().keySet().stream().anyMatch(r -> r.contains(token));\nif (!covered) throw new IllegalArgumentException(\"token not covered by placements: \" + token);","typeGuard":null,"tryCatchPattern":"try { VersionedEndpoints.ForRange e = replicaGroups.forToken(token); } catch (IllegalStateException e) { /* refresh metadata and retry once */ }","preventionTips":["Always read placements from a fresh ClusterMetadata snapshot before token lookups","After any token operation (bootstrap/replace/move), wait for the metadata epoch to catch up locally","Validate proposed tokens against current range bounds before placement APIs"],"tags":["tcm","ownership","token-metadata","illegal-state"],"backgroundTag":"internal-invariant-violation","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"}