apache/cassandra · error · InvalidRequestException

ttl is too large. requested (%d) maximum (%d)

Error message

ttl is too large. requested (%d) maximum (%d)

What it means

Cassandra caps USING TTL at MAX_TTL (20 years, 630720000 seconds) because stored expiration timestamps are 32-bit; larger TTLs would overflow. getTimeToLive throws InvalidRequestException 'ttl is too large. requested (%d) maximum (%d)'. (Expiration-date overflow beyond 2038 is further handled by ExpirationDateOverflowHandling.)

Source

Thrown at src/java/org/apache/cassandra/cql3/Attributes.java:143

        // 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)
    {
        if (timestamp != null)
            timestamp.collectMarkerSpecification(boundNames, this);
        if (timeToLive != null)
            timeToLive.collectMarkerSpecification(boundNames, this);
    }

    public static class Raw

View on GitHub (pinned to 88fd0f6a0e)

Solutions

  1. Cap the TTL client-side to 630720000 (20 years) or use TTL 0 for no expiry
  2. Convert milliseconds to seconds before binding (ms / 1000)
  3. Express 'never expire' as TTL 0 rather than a very large number
  4. Review retention logic so computed TTLs stay within 32-bit-second limits

Example fix

// before
int ttl = (int) (retentionMs / 1); // wrong unit, huge value
// after
int ttl = (int) Math.min(retentionMs / 1000, 630720000L); // seconds, <= MAX_TTL
Defensive patterns

Strategy: validation

Validate before calling

static final int MAX_TTL = 630720000; // 20 years
int clampTtl(long ttlSeconds) {
    return (int) Math.min(Math.max(ttlSeconds, 0), MAX_TTL);
}

Type guard

boolean isTtlWithinLimit(long ttl) { return ttl >= 0 && ttl <= 630720000L; }

Try / catch

try {
    session.execute(bs);
} catch (InvalidQueryException e) {
    if (e.getMessage().startsWith("ttl is too large"))
        log.error("TTL exceeds 20 years; convert ms->s or use TTL 0 for no expiry");
    throw e;
}

Prevention

When it happens

Trigger: 'USING TTL ?' bound with an int > 630720000 (20 years); e.g. computing a TTL in seconds from a multi-decade retention period or accidentally using milliseconds (e.g. 31536000000 = 1000 years in ms).

Common situations: Retention policies expressed in ms bound directly as TTL seconds; 'infinite' retention encoded as Integer.MAX_VALUE; business rules like 'never expire' mapped to huge numbers.

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


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/3d7205c142d5accf. Report an issue: GitHub.