apache/cassandra · error · UnsupportedOperationException

You can't mix sstables from different directories in a compa

Error message

You can't mix sstables from different directories in a compaction

What it means

validateForCompaction also requires all sstables in one compaction task to belong to the same compaction strategy holder index, which in disk-boundary mode corresponds to the same data directory. Compacting sstables from different directories in one task would break the per-directory split that keeps directory-level disk usage and lifecycle balanced, so UnsupportedOperationException is thrown.

Source

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

    }

    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<>();

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Group requested sstables by their directory (compactionStrategyIndexFor / sstable directory) and compact each group separately
  2. Compact per directory: nodetool compact on sstables sharing one data_file_directory
  3. Disable split-disk-boundaries (data_file_directories to a single dir) if JBOD split is not required, then compact
  4. Upgrade Cassandra - later versions improved user-defined compaction handling across disk boundaries

Example fix

// before
getUserDefinedTasks(allSstables, gcBefore); // spans directories
// after
Map<Integer, List<SSTableReader>> byIdx = allSstables.stream().collect(Collectors.groupingBy(csm::compactionStrategyIndexFor));
byIdx.values().forEach(g -> getUserDefinedTasks(g, gcBefore));
Defensive patterns

Strategy: validation

Validate before calling

long dirs = sstables.stream().map(s -> s.descriptor.directory).distinct().count();
if (dirs > 1) throw new IllegalArgumentException("compact per data_file_directory, not across directories");

Try / catch

try { getUserDefinedTasks(input, gcBefore); }
catch (UnsupportedOperationException e) {
  Map<String, List<SSTableReader>> byDir = groupByDirectory(input);
  byDir.values().forEach(g -> getUserDefinedTasks(g, gcBefore));
}

Prevention

When it happens

Trigger: User-defined compaction (nodetool compact --sstable or getUserDefinedTasks) given sstable readers residing under different data_file_directories on a JBOD setup with disk boundaries in effect.

Common situations: JBOD/multi-directory deployments where ops scripts compact across the whole table by listing all sstables; after adding a disk, sstables span directory holders; tooling written before the disk-boundary split existed.

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/93df8ddceae4fbd0. Report an issue: GitHub.