apache/cassandra · error · IllegalStateException

No SSTables available for training in table <keyspaceName>.<

Error message

No SSTables available for training in table <keyspaceName>.<tableName> after flush

What it means

When training is triggered without existing SSTables, train() forces a blocking flush and then selects a referenced view of canonical SSTables. If the flush produces no SSTables (nothing to flush), training cannot proceed and IllegalStateException is thrown. A dictionary needs sample data from SSTables to train on.

Source

Thrown at src/java/org/apache/cassandra/db/compression/CompressionDictionaryManager.java:208

        checkTrainingFrequency(dictionary, trainingConfig);

        // SSTable-based training: sample from existing SSTables

        // this is not closed here but in training runnable when finished
        // also, if view is empty, and we throw just below because of it then
        // there is nothing to "release" so close is not necessary
        ColumnFamilyStore.RefViewFragment refViewFragment = columnFamilyStore.selectAndReference(View.selectFunction(SSTableSet.CANONICAL));

        if (refViewFragment.sstables.isEmpty())
        {
            logger.info("No SSTables available for training in table {}.{}, flushing memtable first", keyspaceName, tableName);
            columnFamilyStore.forceBlockingFlush(ColumnFamilyStore.FlushReason.USER_FORCED);

            refViewFragment = columnFamilyStore.selectAndReference(View.selectFunction(SSTableSet.CANONICAL));

            if (refViewFragment.sstables.isEmpty())
            {
                throw new IllegalStateException("No SSTables available for training in table " + keyspaceName + '.' + tableName + " after flush");
            }
        }

        scheduler.scheduleSSTableBasedTraining(refViewFragment,
                                               compressionParams,
                                               trainingConfig,
                                               this::handleNewDictionary,
                                               force);
    }

    @Override
    public CompositeData getTrainingState()
    {
        return scheduler.getLastTrainingState().toCompositeData();
    }

    @Override
    public TabularData listCompressionDictionaries()

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Write data to the table and flush (or wait for SSTables to exist) before training.
  2. Guard the training call: only invoke train() when the table has at least one SSTable (check tablemetrics or SSTableSet.CANONICAL view).
  3. If training on a test/empty table, populate sample rows first.
  4. Schedule training only after bulk loads or compactions that leave SSTables behind.

Example fix

// before
manager.train(true, Map.of()); // throws on empty table
// after
if (!columnFamilyStore.getLiveSSTables().isEmpty() || columnFamilyStore.hasUnreclaimedSpace())
    manager.train(true, Map.of());
Defensive patterns

Strategy: validation

Validate before calling

if (columnFamilyStore.getLiveSSTables().isEmpty()) throw new IllegalStateException("skip training: no SSTables");

Try / catch

try { manager.train(true, params); } catch (IllegalStateException e) { /* no SSTables: write data or retry later */ }

Prevention

When it happens

Trigger: Calling train() on a table that has no data in memtables and no existing canonical SSTables: the forceBlockingFlush writes nothing, refViewFragment.sstables is empty, and the error is thrown.

Common situations: Running training on a freshly created/empty table; all data was just compacted away or TTL-expired; calling training immediately after TRUNCATE; automated jobs that train tables on a schedule regardless of data presence.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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