apache/cassandra · error · RuntimeException

Attempting to compact transient sstables with non transient

Error message

Attempting to compact transient sstables with non transient sstables

What it means

Incremental repair creates 'transient' SSTables on transiently-repaired replicas which must never be compacted with ordinary (non-transient) SSTables, because their data lifetime and promotion semantics differ. getIsTransient() checks that every SSTable in the compaction set agrees on transient status and aborts with this RuntimeException otherwise.

Source

Thrown at src/java/org/apache/cassandra/db/compaction/CompactionTask.java:478

        if (ids.size() != 1)
            throw new RuntimeException(String.format("Attempting to compact pending repair sstables with sstables from other repair, or sstables not pending repair: %s", ids));

        return ids.iterator().next();
    }

    public static boolean getIsTransient(Set<SSTableReader> sstables)
    {
        if (sstables.isEmpty())
        {
            return false;
        }

        boolean isTransient = sstables.iterator().next().isTransient();

        if (!Iterables.all(sstables, sstable -> sstable.isTransient() == isTransient))
        {
            throw new RuntimeException("Attempting to compact transient sstables with non transient sstables");
        }

        return isTransient;
    }


    /*
     * Checks if we have enough disk space to execute the compaction.  Drops the largest sstable out of the Task until
     * there's enough space (in theory) to handle the compaction.
     *
     * @return true if there is enough disk space to execute the complete compaction, false if some sstables are excluded.
     */
    protected boolean buildCompactionCandidatesForAvailableDiskSpace(final Set<SSTableReader> nonExpiredSSTables, boolean containsExpired, TimeUUID taskId)
    {
        if(!cfs.isCompactionDiskSpaceCheckEnabled() && compactionType == OperationType.COMPACTION)
        {
            logger.info("Compaction space check is disabled - trying to compact all sstables");
            return true;

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Keep transient and non-transient SSTables in separate compaction submissions; PendingRepairManager normally does this automatically
  2. Verify transient repair configuration is consistent across the cluster (all nodes support transient replication)
  3. Ensure SSTables produced by transient repair are not manually relocated or re-tagged
  4. If hit during normal operation, treat as an internal invariant violation and file a bug; avoid custom compaction code that bypasses strategy partitioning

Example fix

// before
compactor.compact(allRepairSstables);
// after
Map<Boolean, List<SSTableReader>> byTransient = allRepairSstables.stream().collect(partitioningBy(SSTableReader::isTransient));
byTransient.values().forEach(compactor::compact);
Defensive patterns

Strategy: validation

Validate before calling

boolean t = sstables.iterator().next().isTransient();
if (!Iterables.all(sstables, s -> s.isTransient() == t)) throw new IllegalArgumentException("mixed transient/non-transient sstables");

Prevention

When it happens

Trigger: Submitting a compaction job whose SSTable set contains both transient and non-transient SSTables for the same pending repair session.

Common situations: Running a cluster with transient replication and mixing outputs of full vs transient repair; bugs in PendingRepairManager partitioning; manual SSTable manipulation (e.g. after moving sstables between directories) that loses transient status distinction.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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