apache/cassandra · error · MarshalException
A local deletion time should not be negative in '%s'
Error message
A local deletion time should not be negative in '%s'
What it means
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.
Source
Thrown at src/java/org/apache/cassandra/db/rows/AbstractRow.java:89
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()
{
if (primaryKeyLivenessInfo().isExpiring() && (primaryKeyLivenessInfo().ttl() < 0 || primaryKeyLivenessInfo().localExpirationTime() < 0))
return true;
if (!deletion().time().validate())
return true;
for (ColumnData cd : this)
if (cd.hasInvalidDeletions())
return true;
return false;
}
public String toString()
{View on GitHub (pinned to 88fd0f6a0e)
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).
Example fix
// before
DeletionTime dt = new DeletionTime(ts, negativeLdt);
// after
if (negativeLdt < 0) throw new IllegalArgumentException("invalid localDeletionTime");
DeletionTime dt = new DeletionTime(ts, negativeLdt); Defensive patterns
Strategy: validation
Validate before calling
if (row.deletion().time().localDeletionTime() < 0) throw new IllegalArgumentException("invalid row tombstone"); Try / catch
try { row.validateData(metadata); } catch (MarshalException e) { scrubTable(metadata.keyspace, metadata.name); } Prevention
- 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
When it happens
Trigger: 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.
Common situations: Disk corruption; third-party bulk loaders writing invalid tombstones; streaming from a node with corrupt data.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- A local deletion time should not be negative
- A TTL should not be negative
- A local deletion time should not be a legacy overflowed valu
- Shoud not have a TTL without an associated local deletion ti
- A TTL should not be negative
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/5418a47f6fdb8d7e.
Report an issue: GitHub.