apache/cassandra · error · IllegalStateException
Missing SAI index to import for index %s on %s.%s
Error message
Missing SAI index to import for index %s on %s.%s
What it means
During SSTable import, SSTableImporter verifies that each SAI per-column index registered on the table has finished building for this SSTable (isPerSSTableIndexBuildComplete per IndexIdentifier). If any per-column index build is incomplete it throws IllegalStateException naming the index, keyspace, and table.
Source
Thrown at src/java/org/apache/cassandra/db/SSTableImporter.java:128
{
IndexDescriptor indexDescriptor = IndexDescriptor.create(descriptor,
cfs.getPartitioner(),
cfs.metadata().comparator);
String keyspace = cfs.getKeyspaceName();
String table = cfs.getTableName();
if (!indexDescriptor.isPerSSTableIndexBuildComplete())
throw new IllegalStateException(String.format("Missing SAI index to import for SSTable %s on %s.%s",
indexDescriptor.sstableDescriptor.toString(),
keyspace,
table));
for (Index index : saiIndexGroup.getIndexes())
{
IndexIdentifier indexIdentifier = new IndexIdentifier(keyspace, table, index.getIndexMetadata().name);
if (!indexDescriptor.isPerColumnIndexBuildComplete(indexIdentifier))
throw new IllegalStateException(String.format("Missing SAI index to import for index %s on %s.%s",
index.getIndexMetadata().name,
keyspace,
table));
}
}
}
if (options.verifySSTables || options.verifyTokens)
verifySSTableForImport(descriptor, entry.getValue(), options.verifyTokens, options.verifySSTables, options.extendedVerify);
}
catch (Throwable t)
{
if (dir != null)
{
logger.error("[{}] Failed verifying SSTable {} in directory {}", importID, descriptor, dir, t);
failedDirectories.add(dir);
}
elseView on GitHub (pinned to 88fd0f6a0e)
Solutions
- Wait for the SAI index build/backfill to finish on the source before copying SSTables
- Copy all SSTable components including the per-column SAI index files for every indexed column
- Rebuild the specific index before import (drop/recreate or use nodetool rebuild_index)
- Import without the index: drop the SAI index, import, then recreate the index on the destination
Example fix
// before: importing during CREATE INDEX backfill nodetool import -- ks table /data/import // after: recreate the index after import instead nodetool drop_index ks table idx && nodetool import -- ks table /data/import cqlsh> CREATE CUSTOM INDEX idx ON ks.table (col) USING 'StorageAttachedIndexing';
Defensive patterns
Strategy: validation
Prevention
- Do not copy SSTables while CREATE INDEX backfill is running; check build status first
- Include every per-column SAI index file in backups/imports
- Drop SAI indexes before large copy operations and recreate them after import
- Use nodetool snapshots as the source for SSTable imports
When it happens
Trigger: importNewSSTables iterates saiIndexGroup.getIndexes(); for one index the SSTable's descriptor reports isPerColumnIndexBuildComplete(indexIdentifier) == false at import time.
Common situations: Importing SSTables copied while a new SAI index (per-column) was still being built/backfilled; partial file copy missing one column's SAI index file; restore from snapshot taken during CREATE INDEX backfill.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Missing SAI index to import for SSTable %s on %s.%s
- Failed verifying SSTable <descriptor>
- Failed importing SSTables
- Failed adding SSTables
- SSTables import has been aborted
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/98bba329c36a409f.
Report an issue: GitHub.