apache/cassandra · error · UnsupportedOperationException

You can't compact sstables from different pending repair ses

Error message

You can't compact sstables from different pending repair sessions

What it means

When sstables are pending an incremental repair (isPendingRepair), each belongs to one pending repair session identified by its pendingRepair TimeUUID. validateForCompaction throws UnsupportedOperationException if a compaction input mixes sstables from different pending-repair sessions, because compacting them would merge anti-compacted data belonging to distinct repair sessions and corrupt repair bookkeeping.

Source

Thrown at src/java/org/apache/cassandra/db/compaction/CompactionStrategyManager.java:1231

    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-enabled
        return cfs.runWithCompactionsDisabled(() -> {
            List<AbstractCompactionTask> tasks = new ArrayList<>();
            readLock.lock();
            try

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Wait for the incremental repairs to finish (or release the sessions) so pending sstables are transitioned out of pending state, then compact
  2. Group sstables by pendingRepair id and issue one compaction per session (only while the session is still active is even that restricted)
  3. Use repair_admin to cancel/abort stale sessions, then nodetool garbagcollect or restart cleanup to clear pending markers
  4. Avoid user-defined compaction of pending sstables entirely; let repair finish first

Example fix

// before
getUserDefinedTasks(pendingSstables, gcBefore); // multiple sessions
// after
Map<TimeUUID, List<SSTableReader>> bySession = pendingSstables.stream().collect(Collectors.groupingBy(s -> s.getSSTableMetadata().pendingRepair));
bySession.values().forEach(g -> getUserDefinedTasks(g, gcBefore));
Defensive patterns

Strategy: validation

Validate before calling

boolean multipleSessions = sstables.stream()
    .filter(SSTableReader::isPendingRepair)
    .map(s -> s.getSSTableMetadata().pendingRepair).distinct().count() > 1;
if (multipleSessions) throw new IllegalArgumentException("one compaction per pending repair session");

Try / catch

try { getUserDefinedTasks(input, gcBefore); }
catch (UnsupportedOperationException e) {
  // wait for repair sessions to finish or group by pendingRepair id and retry
}

Prevention

When it happens

Trigger: User-defined compaction selecting pending-repair sstables from more than one incremental repair session (different pendingRepair ids) while the first sstable isPending - checked via sstable.getSSTableMetadata().pendingRepair inequality.

Common situations: Running concurrent incremental repairs on the same table then attempting manual compaction of pending sstables; repair sessions abandoned without release; repair-adjacent tooling that collects all pending sstables into one compact call.

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


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/a22a4bda9a7e0f9f. Report an issue: GitHub.