{"record":{"id":"9d474b02e60705f6","repo":"apache/cassandra","slug":"missing-sai-index-to-import-for-sstable-s-on-s","errorCode":null,"errorMessage":"Missing SAI index to import for SSTable %s on %s.%s","messagePattern":"Missing SAI index to import for SSTable (.+?) on (.+?)\\.(.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/SSTableImporter.java","lineNumber":119,"sourceCode":"                    {\n                        try\n                        {\n                            abortIfDraining();\n\n                            if (options.failOnMissingIndex)\n                            {\n                                Index.Group saiIndexGroup = cfs.indexManager.getIndexGroup(StorageAttachedIndexGroup.GROUP_KEY);\n                                if (saiIndexGroup != null)\n                                {\n                                    IndexDescriptor indexDescriptor = IndexDescriptor.create(descriptor,\n                                                                                             cfs.getPartitioner(),\n                                                                                             cfs.metadata().comparator);\n\n                                    String keyspace = cfs.getKeyspaceName();\n                                    String table = cfs.getTableName();\n\n                                    if (!indexDescriptor.isPerSSTableIndexBuildComplete())\n                                        throw new IllegalStateException(String.format(\"Missing SAI index to import for SSTable %s on %s.%s\",\n                                                                                      indexDescriptor.sstableDescriptor.toString(),\n                                                                                      keyspace,\n                                                                                      table));\n\n                                    for (Index index : saiIndexGroup.getIndexes())\n                                    {\n                                        IndexIdentifier indexIdentifier = new IndexIdentifier(keyspace, table, index.getIndexMetadata().name);\n                                        if (!indexDescriptor.isPerColumnIndexBuildComplete(indexIdentifier))\n                                            throw new IllegalStateException(String.format(\"Missing SAI index to import for index %s on %s.%s\",\n                                                                                          index.getIndexMetadata().name,\n                                                                                          keyspace,\n                                                                                          table));\n                                    }\n                                }\n                            }\n\n                            if (options.verifySSTables || options.verifyTokens)\n                                verifySSTableForImport(descriptor, entry.getValue(), options.verifyTokens, options.verifySSTables, options.extendedVerify);","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/SSTableImporter.java#L101-L137","documentation":"SSTableImporter.importNewSSTables refuses to import an SSTable whose SAI (Storage-Attached Index) per-SSTable index build is not complete. Importing such an SSTable would attach a table with missing/incomplete index files, so it throws IllegalStateException naming the descriptor, keyspace, and table.","triggerScenarios":"Running `nodetool import` (SSTableImporter.importNewSSTables) on an SSTable whose sstable Descriptor has isPerSSTableIndexBuildComplete() == false — i.e., SAI index files are absent or were not finished being built before the SSTable was copied into the import directory.","commonSituations":"Copying SSTables from a node while an SAI index build/rebuild was still in progress; manually copying only the -Data.db files without the SAI index components; restoring a backup taken mid index-build.","solutions":["Ensure the SSTable is fully built: rebuild SAI indexes (`nodetool indexupgrade`/rebuild the index or run a full index build) before importing","Copy the complete SSTable component set including SAI index files (`.db`, `-CompressionInfo`, SAI per-column/per-sstable files) from a healthy source","Take backups only after index builds complete, or run a fresh index build after import on the target","If SAI is not needed for the import, drop and recreate the index on the destination after import"],"exampleFix":"// before: importing an SSTable with incomplete SAI files\nnodetool import -- ks table /data/import\n// after: rebuild the SAI index first, then import\nnodetool rebuild_index ks table idx\nnodetool import -- ks table /data/import","handlingStrategy":"validation","validationCode":"// before import: check SAI per-sstable build completeness marker exists\nFile saiMarker = new File(importDir, sstableBase + \".db\");\nif (!hasCompleteSaiComponents(importDir)) {\n    throw new IllegalStateException(\"SAI index components incomplete; rebuild index before import\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Copy SSTables only after index builds complete on the source","Always copy the full SSTable component set, including SAI files","Prefer snapshots (nodetool snapshot) over raw directory copies for SAI tables","Plan to rebuild indexes on the destination after restore"],"tags":["sai","sstable","import","index-build"],"backgroundTag":"invalid-state-transition","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}