apache/cassandra · error · MarshalException

comparator #%s '%s' in '%s' didn't validate

Error message

comparator #%s '%s' in '%s' didn't validate

What it means

validateClustering checks each clustering-key component of a row against the comparator (clustering type) declared by the table metadata at position i. If the raw bytes cannot be validated by that AbstractType, the value does not conform to the schema — typically because the row is being read/written against mismatched or altered schema — and a MarshalException wrapping the cause is thrown.

Source

Thrown at src/java/org/apache/cassandra/db/rows/AbstractRow.java:77

        apply(ColumnData::digest, digest);
    }

    private <V> void validateClustering(TableMetadata metadata, Clustering<V> clustering)
    {
        ValueAccessor<V> accessor = clustering.accessor();
        for (int i = 0; i < clustering.size(); i++)
        {
            V value = clustering.get(i);
            if (value != null)
            {
                try
                {
                    metadata.comparator.subtype(i).validate(value, accessor);
                }
                catch (Exception e)
                {
                    throw new MarshalException("comparator #" + i + " '" + metadata.comparator.subtype(i) + "' in '" + metadata + "' didn't validate", e);
                }
            }
        }
    }

    public void validateData(TableMetadata metadata)
    {
        validateClustering(metadata, clustering());

        primaryKeyLivenessInfo().validate();
        if (deletion().time().localDeletionTime() < 0)
            throw new MarshalException("A local deletion time should not be negative in '" + metadata + "'");

        apply(cd -> cd.validate());
    }

    public boolean hasInvalidDeletions()
    {

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Ensure schema agreement across the cluster (`nodetool describecluster`) before reading/writing.
  2. Restore the original column type via ALTER TABLE if the type change was unintended, or drop and recreate the table and reload correct data.
  3. Scrub the affected SSTables to drop rows with invalid clustering keys.
  4. Verify the SSTable belongs to this table (check its metadata/stats) if files were moved or restored.

Example fix

// before: reading SSTables after schema drift
SELECT * FROM myks.mytable; // MarshalException: comparator #0 ...
// after: align schema first, then scrub
ALTER TABLE myks.mytable ALTER c1 TYPE int; // match original type
nodetool scrub myks mytable;
Defensive patterns

Strategy: try-catch

Validate before calling

for (int i = 0; i < clustering.size(); i++) metadata.comparator.subtype(i).validate(clustering.get(i), ByteBufferAccessor.instance);

Try / catch

try { row.validateClustering(metadata, clustering); } catch (MarshalException e) { logger.error("schema mismatch on clustering key", e); verifySchemaAgreement(); }

Prevention

When it happens

Trigger: Reading data whose serialized clustering key does not match the table's current clustering types (e.g. after an ALTER TYPE on a clustering column); deserializing a partition written with a different schema; corrupt clustering key bytes.

Common situations: Schema changes (ALTER TABLE on clustering column types) applied on some nodes but not others; applying wrong SSTables from another table; corrupted sstable files.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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