{"record":{"id":"271611d4aed87cdd","repo":"apache/cassandra","slug":"couldn-t-acquire-reference-to-the-sstable-s","errorCode":null,"errorMessage":"Couldn't acquire reference to the sstable: %s","messagePattern":"Couldn't acquire reference to the sstable: (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/index/sasi/SSTableIndex.java","lineNumber":59,"sourceCode":"import org.apache.cassandra.utils.concurrent.Ref;\n\npublic class SSTableIndex implements Comparable<SSTableIndex>\n{\n    private final ColumnIndex columnIndex;\n    private final Ref<SSTableReader> sstableRef;\n    private final SSTableReader sstable;\n    private final OnDiskIndex index;\n    private final AtomicInteger references = new AtomicInteger(1);\n    private final AtomicBoolean obsolete = new AtomicBoolean(false);\n\n    public SSTableIndex(ColumnIndex index, File indexFile, SSTableReader referent)\n    {\n        this.columnIndex = index;\n        this.sstableRef = referent.tryRef();\n        this.sstable = sstableRef.get();\n\n        if (sstable == null)\n            throw new IllegalStateException(\"Couldn't acquire reference to the sstable: \" + referent);\n\n        AbstractType<?> validator = columnIndex.getValidator();\n\n        assert validator != null;\n        assert indexFile.exists() : String.format(\"SSTable %s should have index %s.\",\n                sstable.getFilename(),\n                columnIndex.getIndexName());\n\n        this.index = new OnDiskIndex(indexFile, validator, new DecoratedKeyFetcher(sstable));\n    }\n\n    public OnDiskIndexBuilder.Mode mode()\n    {\n        return index.mode();\n    }\n\n    public boolean hasMarkedPartials()\n    {","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/index/sasi/SSTableIndex.java#L41-L77","documentation":"SSTableIndex construction takes a reference on the owning SSTable (referent.tryRef()). If the SSTable was just replaced/deleted by compaction or cleanup, tryRef returns null and the constructor throws this IllegalStateException, preventing an index on a dead SSTable from being used.","triggerScenarios":"Building a SSTableIndex during query planning or compaction when the referenced SSTable is concurrently discarded: the Ref.tryRef() fails because refcount is zero or the ref tracker is already cleaned up.","commonSituations":"Heavy compaction activity concurrent with queries on SASI-indexed tables; node restart/cleanup racing with index reads; loading a corrupted or already-obsoleted per-sstable index file.","solutions":["Retry the query — the per-sstable index view is rebuilt and the dead SSTable is dropped from the set.","Force a compaction or rebuild the SASI index (nodetool compact, or drop/recreate the index) so indexes reference live SSTables.","If it recurs persistently, check for GC/ref-tracking bugs or mismatched on-disk index files and run nodetool scrub/upgradeSSTables."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    return runSasiQuery();\n} catch (IllegalStateException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"Couldn't acquire reference to the sstable\"))\n        return retryWithBackoff(runSasiQuery); // index view rebuilt on retry\n    throw e;\n}","preventionTips":["Avoid aggressive concurrent compaction (concurrent_compactors, compaction throughput) during index-heavy workloads.","Retry SASI queries once on transient lifecycle exceptions.","Keep index files and SSTables in sync; avoid manually deleting SSTable components."],"tags":["sasi","reference-counting","sstable-lifecycle","race-condition","cassandra"],"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-17T15:17:12.973Z"}