{"record":{"id":"5c2bc5d20de36f9e","repo":"apache/cassandra","slug":"requested-range-s-intersects-a-local-range-s-b","errorCode":null,"errorMessage":"Requested range %s intersects a local range (%s) but is not fully contained in one; this would lead to imprecise repair. keyspace: %s","messagePattern":"Requested range (.+?) intersects a local range \\((.+?)\\) but is not fully contained in one; this would lead to imprecise repair\\. keyspace: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/service/ActiveRepairService.java","lineNumber":598,"sourceCode":"     * @param keyspaceLocalRanges local-range for given keyspaceName\n     * @param toRepair            token to repair\n     * @return neighbors with whom we share the provided range\n     */\n    public EndpointsForRange getNeighbors(String keyspaceName, Iterable<Range<Token>> keyspaceLocalRanges, Range<Token> toRepair)\n    {\n        StorageService ss = StorageService.instance;\n        EndpointsByRange replicaSets = ss.getRangeToAddressMap(keyspaceName);\n        Range<Token> rangeSuperSet = null;\n        for (Range<Token> range : keyspaceLocalRanges)\n        {\n            if (range.contains(toRepair))\n            {\n                rangeSuperSet = range;\n                break;\n            }\n            else if (range.intersects(toRepair))\n            {\n                throw new IllegalArgumentException(String.format(\"Requested range %s intersects a local range (%s) \" +\n                                                                 \"but is not fully contained in one; this would lead to \" +\n                                                                 \"imprecise repair. keyspace: %s\", toRepair, range, keyspaceName));\n            }\n        }\n        if (rangeSuperSet == null || !replicaSets.containsKey(rangeSuperSet))\n            return EndpointsForRange.empty(toRepair);\n\n        // same as withoutSelf(), but done this way for testing\n        return replicaSets.get(rangeSuperSet).filter(r -> !ctx.broadcastAddressAndPort().equals(r.endpoint()));\n    }\n\n\n    /**\n     * Return all of the neighbors in the listed data center or host lists\n     *\n     * @param toRepair            token to repair\n     * @param dataCenters         the data centers to involve in the repair\n     * @return neighbors with whom we share the provided range","sourceCodeStart":580,"sourceCodeEnd":616,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/service/ActiveRepairService.java#L580-L616","documentation":"getNeighbors validates that every requested repair range either fully contains a local token range or does not intersect it at all. A requested range that partially overlaps a local range would produce an imprecise repair (some subranges repaired, others not), so Cassandra rejects it with IllegalArgumentException instead of silently repairing incorrectly.","triggerScenarios":"Calling nodetool repair (or StorageService.repair) with -st/-et start/end tokens such that the range [st,et] intersects but does not contain a local primary range, e.g. splitting a repair range mid-token-range.","commonSituations":"Operators computing token ranges for parallelized repair with incorrect boundaries; tools that chunk the token space without respecting ring range boundaries (range boundaries must align with local ranges).","solutions":["Align -st/-et with actual ring range boundaries (use nodetool ring / system.local token metadata)","Repair the full local range by not passing -st/-et, or use -pr","Compute requested ranges from the local ranges of the node rather than arbitrary splits"],"exampleFix":"// before\nnodetool repair -st 100 -et 200 keyspace1  // 200 cuts a local range in half\n// after\nnodetool repair -st 100 -et 350 keyspace1   // end aligned to range boundary","handlingStrategy":"validation","validationCode":"// verify the requested range is contained in a single local range before repair\nList<Range<Token>> localRanges = storageService.getLocalRanges(keyspace);\nboolean ok = localRanges.stream().anyMatch(r -> r.contains(requested));","typeGuard":null,"tryCatchPattern":"try { repairNeighbors = ActiveRepairService.instance.getNeighbors(...); }\ncatch (IllegalArgumentException e) { log.error(\"misaligned -st/-et range\", e); }","preventionTips":["Derive sub-ranges from getLocalRanges() rather than arbitrary token splits","Use -pr or full-range repair when unsure about boundaries"],"tags":["repair","token-ranges","validation"],"backgroundTag":"invalid-argument-value","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"}