apache/cassandra · error · IOException
Unsupported SSTable version /
Error message
Unsupported SSTable version /
What it means
Util.metadataFromSSTable reconstructs TableMetadata by reading the Stats.db component of an SSTable Descriptor, and throws IOException when the descriptor's SSTable version is not compatible with the running code. It reports the format name and version so you can see which legacy/unknown sstable was passed.
Solutions
- Run the tool from a Cassandra version whose sstable version is compatible with the file (upgrade the tool, not the file)
- Use the matching major version: check desc.getFormat().name() in the message to identify which release wrote it
- If the file is legacy, upgrade the sstables with upgradesstables on an intermediate Cassandra release before reading
- Verify you did not mix sstables from different Cassandra versions in the same directory
Defensive patterns
Strategy: try-catch
Validate before calling
if (!desc.version.isCompatible())
throw new IOException("Refusing to read sstable " + desc + ": unsupported version " + desc.version); Try / catch
try {
TableMetadata md = Util.metadataFromSSTable(desc);
} catch (IOException e) {
if (e.getMessage().startsWith("Unsupported SSTable version")) {
// switch to a compatible tool/Cassandra version
} else {
throw e;
}
} Prevention
- Match tool version to the Cassandra version that wrote the sstable
- Check Descriptor.version before processing files
- Don't mix sstables from different Cassandra versions
When it happens
Trigger: Pointing offline tools (sstablemetadata, sstabledump, metadataFromSSTable) at an sstable written by a version too old (e.g. 'ma'/'mc' after support was dropped) or by a newer Cassandra than the tool being run.
Common situations: Upgrading Cassandra but running the old tools against new sstables; restoring a backup from an ancient version; copying sstables from a newer cluster into an older one.
Related errors
- Cannot read index summary because min_index_interval…
- Cannot remove temporary or obsoleted files for
- Cannot remove temporary or obsoleted files for
- Checksums do not match for
- Corrupt flags value for clustering prefix (isStatic flag…
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/24259a6fd00698cb.
Report an issue: GitHub.
Appendix: source
Thrown at src/java/org/apache/cassandra/tools/Util.java:315
}
public static <T> Stream<T> iterToStream(Iterator<T> iter)
{
Spliterator<T> splititer = Spliterators.spliteratorUnknownSize(iter, Spliterator.IMMUTABLE);
return StreamSupport.stream(splititer, false);
}
/**
* Construct table schema from info stored in SSTable's Stats.db
*
* @param desc SSTable's descriptor
* @return Restored CFMetaData
* @throws IOException when Stats.db cannot be read
*/
public static TableMetadata metadataFromSSTable(Descriptor desc) throws IOException
{
if (!desc.version.isCompatible())
throw new IOException("Unsupported SSTable version " + desc.getFormat().name() + "/" + desc.version);
StatsComponent statsComponent = StatsComponent.load(desc, MetadataType.STATS, MetadataType.HEADER);
SerializationHeader.Component header = statsComponent.serializationHeader();
IPartitioner partitioner = FBUtilities.newPartitioner(desc);
TableMetadata.Builder builder = TableMetadata.builder("keyspace", "table").partitioner(partitioner).offline();
header.getStaticColumns().entrySet().stream()
.forEach(entry -> {
ColumnIdentifier ident = ColumnIdentifier.getInterned(UTF8Type.instance.getString(entry.getKey()), true);
builder.addStaticColumn(ident, entry.getValue());
});
header.getRegularColumns().entrySet().stream()
.forEach(entry -> {
ColumnIdentifier ident = ColumnIdentifier.getInterned(UTF8Type.instance.getString(entry.getKey()), true);
builder.addRegularColumn(ident, entry.getValue());
});
builder.addPartitionKeyColumn("PartitionKey", header.getKeyType());View on GitHub (pinned to 88fd0f6a0e)