{"record":{"id":"5418a47f6fdb8d7e","repo":"apache/cassandra","slug":"a-local-deletion-time-should-not-be-negative-in","errorCode":null,"errorMessage":"A local deletion time should not be negative in '%s'","messagePattern":"A local deletion time should not be negative in '(.+?)'","errorType":"validation","errorClass":"MarshalException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/db/rows/AbstractRow.java","lineNumber":89,"sourceCode":"                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    {\n        if (primaryKeyLivenessInfo().isExpiring() && (primaryKeyLivenessInfo().ttl() < 0 || primaryKeyLivenessInfo().localExpirationTime() < 0))\n            return true;\n        if (!deletion().time().validate())\n            return true;\n        for (ColumnData cd : this)\n            if (cd.hasInvalidDeletions())\n                return true;\n        return false;\n    }\n\n    public String toString()\n    {","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/db/rows/AbstractRow.java#L71-L107","documentation":"AbstractRow.validateData validates a full row against table metadata. The row-level deletion (tombstone) time must be non-negative; a negative localDeletionTime in the row's DeletionTime means corrupted or malformed data, rejected with MarshalException including the table name.","triggerScenarios":"Deserializing a row whose row-tombstone deletion time bytes are corrupted; reading SSTables/commitlog/stream sections written by a buggy encoder; manual data import with malformed tombstones.","commonSituations":"Disk corruption; third-party bulk loaders writing invalid tombstones; streaming from a node with corrupt data.","solutions":["Run `nodetool scrub` on the affected table to drop invalid rows.","Restore affected data files from backup.","Check hardware/filesystem for corruption.","Fix any custom loader/serializer so tombstone localDeletionTime is always >= 0 (use NO_DELETION_TIME = Int.MAX_VALUE when there is no deletion)."],"exampleFix":"// before\nDeletionTime dt = new DeletionTime(ts, negativeLdt);\n// after\nif (negativeLdt < 0) throw new IllegalArgumentException(\"invalid localDeletionTime\");\nDeletionTime dt = new DeletionTime(ts, negativeLdt);","handlingStrategy":"validation","validationCode":"if (row.deletion().time().localDeletionTime() < 0) throw new IllegalArgumentException(\"invalid row tombstone\");","typeGuard":null,"tryCatchPattern":"try { row.validateData(metadata); } catch (MarshalException e) { scrubTable(metadata.keyspace, metadata.name); }","preventionTips":["Validate bulk-loaded data with validation/scrub first","Use NO_DELETION_TIME for absence of deletion in custom writers","Audit third-party bulk loaders for tombstone handling"],"tags":["validation","tombstone","data-corruption","marshal"],"backgroundTag":"value-out-of-range","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"}