apache/cassandra · error
Invalid TTL: %s
Error message
Invalid TTL: %s
What it means
While deserializing a cell from the wire (or an SSTable via the same code path), Cell.Serializer reads the TTL field. A negative TTL is not representable in the object model and can only come from a corrupt or maliciously crafted payload, so deserialization fails immediately with an IOException, aborting the read of that message/partition.
Source
Thrown at src/java/org/apache/cassandra/db/rows/Cell.java:418
V value = accessor.empty();
if (hasValue)
{
if (helper.canSkipValue(column) || (path != null && helper.canSkipValue(path)))
{
header.getType(column).skipValue(in);
}
else
{
boolean isCounter = localDeletionTime == NO_DELETION_TIME && column.type.isCounter();
value = header.getType(column).read(accessor, in, DatabaseDescriptor.getMaxValueSize());
if (isCounter)
value = helper.maybeClearCounterValue(value, accessor);
}
}
if (ttl < 0)
throw new IOException("Invalid TTL: " + ttl);
localDeletionTime = decodeLocalDeletionTime(localDeletionTime, ttl, helper);
return accessor.factory().cell(column, timestamp, ttl, localDeletionTime, value, path);
}
public <T> long serializedSize(Cell<T> cell, ColumnMetadata column, LivenessInfo rowLiveness, SerializationHeader header)
{
long size = 1; // flags
boolean hasValue = cell.valueSize() > 0;
boolean isDeleted = cell.isTombstone();
boolean isExpiring = cell.isExpiring();
boolean useRowTimestamp = !rowLiveness.isEmpty() && cell.timestamp() == rowLiveness.timestamp();
boolean useRowTTL = isExpiring && rowLiveness.isExpiring() && cell.ttl() == rowLiveness.ttl() && cell.localDeletionTime() == rowLiveness.localExpirationTime();
if (!useRowTimestamp)
size += header.timestampSerializedSize(cell.timestamp());
if ((isDeleted || isExpiring) && !useRowTTL)
size += header.localDeletionTimeSerializedSize(cell.localDeletionTime());View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Identify and drop/scrub the corrupt data source (`nodetool scrub` for SSTables, replay-truncate commitlog if needed).
- Verify internode network integrity (NIC/driver issues) if corruption appears in transit.
- Ensure node versions are compatible (same messaging version) to avoid misparsed fields.
- Restore affected data from backups.
Example fix
// before: writing TTL into a payload without bounds check
out.writeInt((int) ttlOrOverride);
// after
int ttl = (int) ttlOrOverride;
if (ttl < 0) throw new IllegalArgumentException("TTL must be >= 0");
out.writeInt(ttl); Defensive patterns
Strategy: try-catch
Validate before calling
// validate before sending: reject negative TTLs at write time
if (ttl < 0) throw new IllegalArgumentException("Invalid TTL: " + ttl); Try / catch
try { Cell.codec.deserialize(in, version, column, ...); } catch (IOException e) { markSourceCorrupt(e); } Prevention
- Keep node messaging versions homogeneous in the cluster
- Scrub after hardware faults
- Reject negative TTLs in application writes
When it happens
Trigger: Receiving a mutated/corrupted internode message whose cell TTL field is negative; reading a corrupt SSTable region interpreted as TTL bytes; version-skew or deserialization of an attacker-crafted payload.
Common situations: Network corruption or buffer handling bugs; corrupted commitlog/SSTable files; fuzzing or crafted streaming payloads between nodes.
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
- Corrupt (negative) value length encountered
- A TTL should not be negative
- Shoud not have a TTL without an associated local deletion ti
- Invalid TTL value: <tval>
- A TTL must be greater or equal to 0, but was <ttl>
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/8b9a61763ff7150c.
Report an issue: GitHub.