{"record":{"id":"aee6efe07e51053d","repo":"apache/cassandra","slug":"attempting-to-compact-pending-repair-sstables-with","errorCode":null,"errorMessage":"Attempting to compact pending repair sstables with sstables from other repair, or sstables not pending repair: %s","messagePattern":"Attempting to compact pending repair sstables with sstables from other repair, or sstables not pending repair: (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/compaction/CompactionTask.java","lineNumber":462,"sourceCode":"        for (SSTableReader sstable : actuallyCompact)\n            minRepairedAt = Math.min(minRepairedAt, sstable.getSSTableMetadata().repairedAt);\n        if (minRepairedAt == Long.MAX_VALUE)\n            return ActiveRepairService.UNREPAIRED_SSTABLE;\n        return minRepairedAt;\n    }\n\n    public static TimeUUID getPendingRepair(Set<SSTableReader> sstables)\n    {\n        if (sstables.isEmpty())\n        {\n            return ActiveRepairService.NO_PENDING_REPAIR;\n        }\n        Set<TimeUUID> ids = new HashSet<>();\n        for (SSTableReader sstable: sstables)\n            ids.add(sstable.getSSTableMetadata().pendingRepair);\n\n        if (ids.size() != 1)\n            throw new RuntimeException(String.format(\"Attempting to compact pending repair sstables with sstables from other repair, or sstables not pending repair: %s\", ids));\n\n        return ids.iterator().next();\n    }\n\n    public static boolean getIsTransient(Set<SSTableReader> sstables)\n    {\n        if (sstables.isEmpty())\n        {\n            return false;\n        }\n\n        boolean isTransient = sstables.iterator().next().isTransient();\n\n        if (!Iterables.all(sstables, sstable -> sstable.isTransient() == isTransient))\n        {\n            throw new RuntimeException(\"Attempting to compact transient sstables with non transient sstables\");\n        }\n","sourceCodeStart":444,"sourceCodeEnd":480,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/compaction/CompactionTask.java#L444-L480","documentation":"Cassandra groups SSTables by the incremental-repair session that produced them. Before an incremental compaction runs, getPendingRepair() verifies that every SSTable in the set carries the exact same pendingRepair ID; if the set resolves to zero IDs (non-repair SSTables mixed in) or more than one ID (SSTables from different repair sessions), the compaction is aborted with this RuntimeException.","triggerScenarios":"Calling CompactionManager to compact a set of SSTables where some have sstable metadata pendingRepair=null and others have a pendingRepair ID, or where SSTables come from two different incremental repair sessions.","commonSituations":"Incremental repair bookkeeping bugs; manually mixing repaired and unrepaired SSTables in a custom compaction; concurrent incremental repair sessions overlapping on the same table; SSTables left over from an aborted repair being compacted together with active-repair SSTables.","solutions":["Do not compact pending-repair SSTables together with other SSTables; ensure the input set contains only SSTables from a single repair session","Run nodetool repair to completion so pending-repair SSTables are promoted and no longer carry a pendingRepair ID, then compact normally","Check for leaked repair sessions (nodetool listbackups / repair_admin) and cancel stale sessions via RepairRunner or nodetool cancelrepair","If reproducible, report as an incremental-repair bug; this throw indicates an internal invariant violation rather than user error"],"exampleFix":"// before: mixing sstables\nList<SSTableReader> mixed = Stream.concat(pendingRepairSstables.stream(), regularSstables.stream()).collect(toList());\ncompactor.compact(mixed);\n// after: filter to one repair session\nTimeUUID id = pendingRepairSstables.get(0).getSSTableMetadata().pendingRepair;\nList<SSTableReader> single = pendingRepairSstables.stream().filter(s -> id.equals(s.getSSTableMetadata().pendingRepair)).collect(toList());\ncompactor.compact(single);","handlingStrategy":"validation","validationCode":"Set<TimeUUID> ids = sstables.stream().map(s -> s.getSSTableMetadata().pendingRepair).collect(Collectors.toSet());\nif (ids.size() != 1 || ids.contains(null)) throw new IllegalArgumentException(\"sstables must all belong to one pending repair session: \" + ids);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Partition compaction inputs strictly by pendingRepair ID before submission","Let PendingRepairManager/CompactionManager select sstables rather than hand-building sets","Complete or cancel incremental repairs promptly to avoid stale pending sstables"],"tags":["compaction","incremental-repair","internal-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"}