{"record":{"id":"79679a979eb6b11f","repo":"apache/cassandra","slug":"s-sstable-s-s-does-not-intersect-repaired-ran","errorCode":null,"errorMessage":"%s SSTable %s (%s) does not intersect repaired ranges %s, this sstable should not have been included.","messagePattern":"(.+?) SSTable (.+?) \\((.+?)\\) does not intersect repaired ranges (.+?), this sstable should not have been included\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/compaction/CompactionManager.java","lineNumber":1134,"sourceCode":"        logger.info(\"{} Completed anticompaction successfully\", PreviewKind.NONE.logPrefix(sessionID));\n    }\n\n    static void validateSSTableBoundsForAnticompaction(TimeUUID sessionID,\n                                                       Collection<SSTableReader> sstables,\n                                                       RangesAtEndpoint ranges)\n    {\n        List<Range<Token>> normalizedRanges = Range.normalize(ranges.ranges());\n        for (SSTableReader sstable : sstables)\n        {\n            AbstractBounds<Token> bounds = sstable.getBounds();\n\n            if (!Iterables.any(normalizedRanges, r -> (r.contains(bounds.left) && r.contains(bounds.right)) || r.intersects(bounds)))\n            {\n                // this should never happen - in PendingAntiCompaction#getSSTables we select all sstables that intersect the repaired ranges, that can't have changed here\n                String message = String.format(\"%s SSTable %s (%s) does not intersect repaired ranges %s, this sstable should not have been included.\",\n                                               PreviewKind.NONE.logPrefix(sessionID), sstable, bounds, normalizedRanges);\n                logger.error(message);\n                throw new IllegalStateException(message);\n            }\n        }\n\n    }\n\n    @VisibleForTesting\n    static Set<SSTableReader> findSSTablesToAnticompact(Iterator<SSTableReader> sstableIterator, List<Range<Token>> normalizedRanges, TimeUUID parentRepairSession)\n    {\n        Set<SSTableReader> fullyContainedSSTables = new HashSet<>();\n        while (sstableIterator.hasNext())\n        {\n            SSTableReader sstable = sstableIterator.next();\n\n            AbstractBounds<Token> sstableBounds = sstable.getBounds();\n\n            for (Range<Token> r : normalizedRanges)\n            {\n                // ranges are normalized - no wrap around - if first and last are contained we know that all tokens are contained in the range","sourceCodeStart":1116,"sourceCodeEnd":1152,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/compaction/CompactionManager.java#L1116-L1152","documentation":"During anti-compaction (repair), each selected SSTable is verified to intersect the repaired ranges. If none of the normalized repaired ranges intersects the SSTable's bounds, an IllegalStateException is thrown because PendingAntiCompaction#getSSTables should have filtered such SSTables out — this indicates a broken internal invariant.","triggerScenarios":"Running nodetool repair / incremental repair when the set of SSTables obtained for the repaired token ranges contains an SSTable whose bounds fall entirely outside the normalized ranges — typically due to a race where SSTables are replaced/compacted between selection and anti-compaction.","commonSituations":"Concurrent compaction or cleanup running during the repair preparation phase, known races in pending anti-compaction on older 4.0 versions, repair range recalculation differing from the selection-time ranges.","solutions":["Re-run the repair; transient races between SSTable selection and anti-compaction are the usual cause.","Avoid triggering major compactions/cleanup concurrently with repair startup.","Upgrade to a version with the pending anti-compaction race fixes (CASSANDRA-15439-era fixes).","If reproducible, capture sstable metadata and ranges in the logged error and report with logs for diagnosis."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// client-side pre-check before incremental repair\nSet<Range<Token>> ranges = repairRanges; // ensure SSTable selection uses identical normalized ranges","typeGuard":null,"tryCatchPattern":"try { repairCoordinator.repairAsync(keyspace, options); } catch (IllegalStateException e) { if (e.getMessage().contains(\"does not intersect repaired ranges\")) { rerunRepairAfterQuiescing(); } }","preventionTips":["Do not run cleanup/major compactions concurrently with repair startup","Retry transient repair failures once before escalating","Keep the cluster on a version with pending anti-compaction race fixes"],"tags":["repair","anticompaction","invariant"],"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-14T16:17:12.679Z"}