apache/cassandra · critical · CorruptSSTableException

Cannot open ; partitioner does not match system partitioner…

Error message

Cannot open %s; partitioner %s does not match system partitioner %s. Note that the default partitioner starting with Cassandra 1.2 is Murmur3Partitioner, so you will need to edit that to match your old partitioner if upgrading.

What it means

validatePartitioner() compares the partitioner recorded in the SSTable's Validation metadata (Statistics.db) with the partitioner of the table being opened. A mismatch means the SSTable's token ordering is incompatible with the table's partitioner, so it throws CorruptSSTableException pointing at the stats component, with guidance about Murmur3Partitioner being the default since 1.2.

Solutions

  1. Set the table/cluster partitioner to match the SSTable's (edit partitioner in cassandra.yaml or table metadata) — only viable if reconfiguring is acceptable
  2. Rewrite the SSTables with sstableloader into a cluster/table using the correct partitioner
  3. Verify the recorded partitioner via sstablemetadata <data-file> before loading
  4. If truly incompatible, discard and rebuild the data via repair from replicas

Example fix

// before: cassandra.yaml with leftover old partitioner
partitioner: org.apache.cassandra.dht.RandomPartitioner
// after
partitioner: org.apache.cassandra.dht.Murmur3Partitioner
Defensive patterns

Strategy: validation

Validate before calling

// compare partitioners before loading
String sstablePartitioner = sstablemetadata(dataFile).partitioner;
String tablePartitioner = metadata.partitioner.getClass().getCanonicalName();
if (!sstablePartitioner.equals(tablePartitioner)) { fixConfigOrRewrite(); }

Try / catch

try { SSTableReader.open(descriptor, components, metadata); }
catch (CorruptSSTableException e) {
    if (e.getMessage().contains("partitioner") && e.getMessage().contains("does not match")) {
        logger.error("Partitioner mismatch for {}", descriptor);
        alignPartitionerConfigOrUseSstableloader();
    } else throw e;
}

Prevention

When it happens

Trigger: Opening/loading an SSTable whose ValidationMetadata.partitioner differs from metadata.partitioner — e.g. loading SSTables written under RandomPartitioner/ByteOrderedPartitioner into a Murmur3 table, or cassandra.yaml partitioner changed between cluster versions.

Common situations: Upgrades from pre-1.2 clusters with edited/unchanged partitioner settings; copying SSTables between clusters configured with different partitioners; pointing tools at foreign SSTable directories.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/io/sstable/format/SSTableReaderLoadingBuilder.java:130

            throw new CorruptSSTableException(ex, descriptor.baseFile());
        }
    }

    public abstract KeyReader buildKeyReader(TableMetrics tableMetrics) throws IOException;

    protected abstract void openComponents(B builder, SSTable.Owner owner, boolean validate, boolean online) throws IOException;

    /**
     * Check if sstable is created using same partitioner.
     * Partitioner can be null, which indicates older version of sstable or no stats available.
     * In that case, we skip the check.
     */
    protected void validatePartitioner(TableMetadata metadata, ValidationMetadata validationMetadata)
    {
        String partitionerName = metadata.partitioner.getClass().getCanonicalName();
        if (validationMetadata != null && !partitionerName.equals(validationMetadata.partitioner))
        {
            throw new CorruptSSTableException(new IOException(String.format("Cannot open %s; partitioner %s does not match system partitioner %s. " +
                                                                            "Note that the default partitioner starting with Cassandra 1.2 is Murmur3Partitioner, " +
                                                                            "so you will need to edit that to match your old partitioner if upgrading.",
                                                                            descriptor, validationMetadata.partitioner, partitionerName)),
                                              descriptor.fileFor(Components.STATS));
        }
    }

    private TableMetadataRef resolveTableMetadataRef()
    {
        TableMetadataRef metadata;
        if (descriptor.cfname.contains(SECONDARY_INDEX_NAME_SEPARATOR))
        {
            int i = descriptor.cfname.indexOf(SECONDARY_INDEX_NAME_SEPARATOR);
            String indexName = descriptor.cfname.substring(i + 1);
            metadata = Schema.instance.getIndexMetadata(descriptor.ksname, indexName).map(m -> m.ref).orElse(null);
            if (metadata == null)
                throw new AssertionError("Could not find index metadata for index cf " + i);
        }

View on GitHub (pinned to 88fd0f6a0e)