{"record":{"id":"28bc26b103c08d2d","repo":"apache/cassandra","slug":"comparator-s-s-in-s-didn-t-validate","errorCode":null,"errorMessage":"comparator #%s '%s' in '%s' didn't validate","messagePattern":"comparator #(.+?) '(.+?)' in '(.+?)' didn't validate","errorType":"validation","errorClass":"MarshalException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/rows/AbstractRow.java","lineNumber":77,"sourceCode":"\n        apply(ColumnData::digest, digest);\n    }\n\n    private <V> void validateClustering(TableMetadata metadata, Clustering<V> clustering)\n    {\n        ValueAccessor<V> accessor = clustering.accessor();\n        for (int i = 0; i < clustering.size(); i++)\n        {\n            V value = clustering.get(i);\n            if (value != null)\n            {\n                try\n                {\n                    metadata.comparator.subtype(i).validate(value, accessor);\n                }\n                catch (Exception e)\n                {\n                    throw new MarshalException(\"comparator #\" + i + \" '\" + metadata.comparator.subtype(i) + \"' in '\" + metadata + \"' didn't validate\", e);\n                }\n            }\n        }\n    }\n\n    public void validateData(TableMetadata metadata)\n    {\n        validateClustering(metadata, clustering());\n\n        primaryKeyLivenessInfo().validate();\n        if (deletion().time().localDeletionTime() < 0)\n            throw new MarshalException(\"A local deletion time should not be negative in '\" + metadata + \"'\");\n\n        apply(cd -> cd.validate());\n    }\n\n    public boolean hasInvalidDeletions()\n    {","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/rows/AbstractRow.java#L59-L95","documentation":"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.","triggerScenarios":"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.","commonSituations":"Schema changes (ALTER TABLE on clustering column types) applied on some nodes but not others; applying wrong SSTables from another table; corrupted sstable files.","solutions":["Ensure schema agreement across the cluster (`nodetool describecluster`) before reading/writing.","Restore the original column type via ALTER TABLE if the type change was unintended, or drop and recreate the table and reload correct data.","Scrub the affected SSTables to drop rows with invalid clustering keys.","Verify the SSTable belongs to this table (check its metadata/stats) if files were moved or restored."],"exampleFix":"// before: reading SSTables after schema drift\nSELECT * FROM myks.mytable; // MarshalException: comparator #0 ...\n// after: align schema first, then scrub\nALTER TABLE myks.mytable ALTER c1 TYPE int; // match original type\nnodetool scrub myks mytable;","handlingStrategy":"try-catch","validationCode":"for (int i = 0; i < clustering.size(); i++) metadata.comparator.subtype(i).validate(clustering.get(i), ByteBufferAccessor.instance);","typeGuard":null,"tryCatchPattern":"try { row.validateClustering(metadata, clustering); } catch (MarshalException e) { logger.error(\"schema mismatch on clustering key\", e); verifySchemaAgreement(); }","preventionTips":["Check `nodetool describecluster` schema agreement after ALTERs","Never move SSTables between tables","Plan clustering column type changes via table recreation"],"tags":["schema","clustering-key","validation","marshal"],"backgroundTag":"type-mismatch","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"}