apache/cassandra · error · UnsupportedOperationException
You can't mix repaired and unrepaired data in a compaction
Error message
You can't mix repaired and unrepaired data in a compaction
What it means
CompactionStrategyManager.validateForCompaction enforces that a single compaction task never mixes sstables with different repair state, because repaired and unrepaired data must stay in separate sstables (required for repaired-data tracking and incremental repair). When the input collection contains both repaired (repairedAt set) and unrepaired sstables, UnsupportedOperationException is thrown. This guards user-defined compaction requests.
Source
Thrown at src/java/org/apache/cassandra/db/compaction/CompactionStrategyManager.java:1227
}
}
private void validateForCompaction(Iterable<SSTableReader> input)
{
readLock.lock();
try
{
SSTableReader firstSSTable = Iterables.getFirst(input, null);
assert firstSSTable != null;
boolean repaired = firstSSTable.isRepaired();
int firstIndex = compactionStrategyIndexFor(firstSSTable);
boolean isPending = firstSSTable.isPendingRepair();
TimeUUID pendingRepair = firstSSTable.getSSTableMetadata().pendingRepair;
for (SSTableReader sstable : input)
{
if (sstable.isRepaired() != repaired)
throw new UnsupportedOperationException("You can't mix repaired and unrepaired data in a compaction");
if (firstIndex != compactionStrategyIndexFor(sstable))
throw new UnsupportedOperationException("You can't mix sstables from different directories in a compaction");
if (isPending && !pendingRepair.equals(sstable.getSSTableMetadata().pendingRepair))
throw new UnsupportedOperationException("You can't compact sstables from different pending repair sessions");
}
}
finally
{
readLock.unlock();
}
}
public CompactionTasks getMaximalTasks(final long gcBefore, final boolean splitOutput, int permittedParallelism, OperationType operationType)
{
maybeReloadDiskBoundaries();
// runWithCompactionsDisabled cancels active compactions and disables them, then we are able
// to make the repaired/unrepaired strategies mark their own sstables as compacting. Once the
// sstables are marked the compactions are re-enabledView on GitHub (pinned to 88fd0f6a0e)
Solutions
- Partition the sstable list by isRepaired() and issue one compaction request per group
- Exclude repaired sstables from user-defined compaction, letting incremental compaction handle them
- Re-run repair first so the dataset has a consistent repair state, then compact
- Use nodetool compact without an explicit sstable list, which handles grouping automatically
Example fix
// before List<SSTableReader> all = getSSTables(); cfs.getCompactionStrategyManager().getUserDefinedTasks(all, gcBefore); // after Map<Boolean, List<SSTableReader>> byRepaired = all.stream().collect(Collectors.partitioningBy(SSTableReader::isRepaired)); byRepaired.values().forEach(g -> cfs.getCompactionStrategyManager().getUserDefinedTasks(g, gcBefore));
Defensive patterns
Strategy: validation
Validate before calling
boolean mixed = sstables.stream().map(SSTableReader::isRepaired).distinct().count() > 1;
if (mixed) throw new IllegalArgumentException("split sstables by repaired state before user-defined compaction"); Try / catch
try { getUserDefinedTasks(input, gcBefore); }
catch (UnsupportedOperationException e) {
// partition by isRepaired() and retry per group
} Prevention
- Always partition user-compaction inputs on SSTableReader.isRepaired()
- Prefer full-table nodetool compact over hand-picked sstable lists
- Run repair before manual compaction so repair state is uniform
- Educate ops scripts about the repaired/unrepaired split
When it happens
Trigger: Calling getUserDefinedTasks / user-defined compaction (nodetool compact with explicit sstable list, or user-defined compaction API) passing a collection containing a mix of repaired and unrepaired SSTableReaders.
Common situations: Scripted compaction tooling that selects sstables by size/age without filtering on repairedAt; running manual compact after an incremental repair repaired only a subset of files; tooling that ignores the repaired/unrepaired split introduced with CASSANDRA-9143.
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
- You can't compact sstables from different pending repair ses
- Could not reference sstables
- Unable to cancel in-progress compactions for {keyspace}.{tab
- No holder claimed
- No holder claimed isPendingRepair: %s, isPendingRepair %s
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/274cb30868fb995f.
Report an issue: GitHub.