apache/cassandra · error · InvalidRequestException
Invalid TTL value: <tval>
Error message
Invalid TTL value: <tval>
What it means
Attributes.getTimeToLive resolves the USING TTL term; the bound value must be a valid Int32Type-encoded 4-byte int. If Int32Type.instance.validate throws MarshalException, the method throws InvalidRequestException 'Invalid TTL value: <bytes>'. This is a format validation of the bound TTL bytes, separate from range checks.
Source
Thrown at src/java/org/apache/cassandra/cql3/Attributes.java:135
ByteBuffer tval = timeToLive.bindAndGet(context);
if (tval == null)
return 0;
if (tval == ByteBufferUtil.UNSET_BYTE_BUFFER)
return metadata.params.defaultTimeToLive;
// byte[0] and null are the same for Int32Type. UNSET_BYTE_BUFFER is also byte[0] but we rely on pointer
// identity, so need to check this after checking that
if (ByteBufferUtil.EMPTY_BYTE_BUFFER.equals(tval))
return 0;
try
{
Int32Type.instance.validate(tval);
}
catch (MarshalException e)
{
throw new InvalidRequestException("Invalid TTL value: " + tval);
}
int ttl = Int32Type.instance.compose(tval);
if (ttl < 0)
throw new InvalidRequestException("A TTL must be greater or equal to 0, but was " + ttl);
if (ttl > MAX_TTL)
throw new InvalidRequestException(String.format("ttl is too large. requested (%d) maximum (%d)", ttl, MAX_TTL));
if (metadata.params.defaultTimeToLive != LivenessInfo.NO_TTL && ttl == LivenessInfo.NO_TTL)
return LivenessInfo.NO_TTL;
ExpirationDateOverflowHandling.maybeApplyExpirationDateOverflowPolicy(metadata, ttl, false);
return ttl;
}
public void collectMarkerSpecification(VariableSpecifications boundNames)View on GitHub (pinned to 88fd0f6a0e)
Solutions
- Bind the TTL as a Java int through the driver instead of raw buffers
- Encode with Int32Type.instance.decompose(ttl) in custom code
- Ensure the value fits in 32-bit signed int and is 4 bytes big-endian
- Re-check the driver/API used to bind USING TTL values
Example fix
// before ByteBuffer ttlBytes = ByteBuffer.allocate(8).putLong(3600L); // 8 bytes // after ByteBuffer ttlBytes = Int32Type.instance.decompose(3600); // valid int32
Defensive patterns
Strategy: validation
Validate before calling
void validateTtlBytes(ByteBuffer tval) {
try { org.apache.cassandra.db.marshal.Int32Type.instance.validate(tval); }
catch (org.apache.cassandra.serializers.MarshalException e) {
throw new IllegalArgumentException("ttl must be an int32-encoded buffer", e);
}
} Type guard
boolean isIntEncoded(ByteBuffer b) { return b != null && b.remaining() == 4; } Try / catch
try {
session.execute(bs);
} catch (InvalidQueryException e) {
if (e.getMessage().startsWith("Invalid TTL value"))
log.error("Bind USING TTL as int via driver typed setters");
throw e;
} Prevention
- Bind TTL as Java int, never long/string buffers
- Use Int32Type.instance.decompose() for raw encoding
- Keep TTL values within int range before binding
- Test custom bind paths that populate USING TTL terms
When it happens
Trigger: 'USING TTL ?' bound with byte values that are not a valid int32 serialization (wrong length, string bytes, oversized long) through raw term binding paths.
Common situations: Custom query handlers or thrift-era code assembling bound values manually; binding a long TTL into an int slot with a full 8-byte buffer; drivers sending text-encoded numbers.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Invalid timestamp value: <tval>
- A TTL must be greater or equal to 0, but was <ttl>
- ttl is too large. requested (%d) maximum (%d)
- Error decoding JSON value for %s: %s
- Invalid operation (%s) for non-UDT column %s
AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10).
Data as JSON: /api/errors/61b811fc8cee8215.
Report an issue: GitHub.