apache/cassandra · error · InvalidRequestException

Request on table . with %sttl of seconds exceeds maximum…

Error message

Request on table %s.%s with %sttl of %d seconds exceeds maximum supported expiration date of %s. In order to avoid this use a lower TTL, change the expiration date overflow policy or upgrade to a version where this limitation is fixed. See CASSANDRA-14092 and CASSANDRA-14227 for more details.

What it means

When a write's TTL (with its local expiration timestamp) would produce an expiration date beyond the maximum representable value, and the configured policy is EXPIRATION_DATE_OVERFLOW_POLICY = REJECT, ExpirationDateOverflowHandling.maybeApplyExpirationDateOverflowPolicy throws InvalidRequestException, rejecting the write (INSERT/UPDATE with TTL).

Solutions

  1. Lower the TTL in the write (or in ttl_in_seconds default) so the expiration date stays within the maximum (e.g. use seconds not decades).
  2. Change expiration_date_overflow_policy in cassandra.yaml from REJECT to CAP (or WARN) if clamping the expiration is acceptable.
  3. Upgrade to a fixed version where the maximum supported expiration date is extended (CASSANDRA-14092/CASSANDRA-14227).
  4. Fix application code that computes TTL (e.g. passing epoch-based seconds instead of a relative TTL).

Example fix

// before: rejected write
INSERT INTO sensors (id, temp) VALUES (1, 20.5) USING TTL 630720000;
// after: smaller TTL within supported range
INSERT INTO sensors (id, temp) VALUES (1, 20.5) USING TTL 31536000;
Defensive patterns

Strategy: validation

Validate before calling

int maxTtl = (int) ((ExpirationDateOverflowHandling.getMaxExpirationDateTS() - System.currentTimeMillis()) / 1000);
if (ttl > maxTtl) ttl = maxTtl; // or reject client-side

Try / catch

try {
    session.execute(insertWithTtl(ttl));
} catch (InvalidRequestException e) {
    if (e.getMessage().contains("exceeds maximum supported expiration date"))
        retryWithClampedTtl(ttl); // lower TTL or use CAP policy server-side
    else throw e;
}

Prevention

When it happens

Trigger: An INSERT/UPDATE (or batch) sets a very large TTL (default TTL exceeding max_expiration_date_overflow_policy limits, or explicit USING TTL <n>) such that localExpirationTime + ttl exceeds MAXIMUM_EXPIRATION_DATE (~2038/2106 boundary depending on build).

Common situations: Misconfigured default TTL of huge values (e.g. ttl_in_seconds = 630720000 with REJECT policy and an older build); application code passing seconds-in-decades as TTL; clusters that predate the CASSANDRA-14092/14227 fixes where the maximum expiration is capped at 2038 (int seconds).

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/8b2125994dfbbf68. Report an issue: GitHub.

Appendix: source

Thrown at src/java/org/apache/cassandra/db/ExpirationDateOverflowHandling.java:105

                case CAP:
                    ClientWarn.instance.warn(MessageFormatter.arrayFormat(MAXIMUM_EXPIRATION_DATE_EXCEEDED_WARNING, new Object[] { metadata.keyspace,
                                                                                                                                   metadata.name,
                                                                                                                                   isDefaultTTL? "default " : "",
                                                                                                                                   ttl,
                                                                                                                                   getMaxExpirationDateTS()})
                                                             .getMessage());
                case CAP_NOWARN:
                    /**
                     * Capping at this stage is basically not rejecting the request. The actual capping is done
                     * by {@link #computeLocalExpirationTime(long, int)}, which converts the negative TTL
                     * to {@link org.apache.cassandra.db.BufferExpiringCell#MAX_DELETION_TIME}
                     */
                    NoSpamLogger.log(logger, NoSpamLogger.Level.WARN, EXPIRATION_OVERFLOW_WARNING_INTERVAL_MINUTES, TimeUnit.MINUTES, MAXIMUM_EXPIRATION_DATE_EXCEEDED_WARNING,
                                     metadata.keyspace, metadata.name, isDefaultTTL? "default " : "", ttl, getMaxExpirationDateTS());
                    return;

                default:
                    throw new InvalidRequestException(String.format(MAXIMUM_EXPIRATION_DATE_EXCEEDED_REJECT_MESSAGE, metadata.keyspace, metadata.name,
                                                                    isDefaultTTL? "default " : "", ttl, getMaxExpirationDateTS()));
            }
        }
    }

    /**
     * This method computes the {@link Cell#localDeletionTime()}, maybe capping to the maximum representable value
     * which is {@link Cell#MAX_DELETION_TIME}.
     *
     * Please note that the {@link ExpirationDateOverflowHandling.ExpirationDateOverflowPolicy} is applied
     * during {@link ExpirationDateOverflowHandling#maybeApplyExpirationDateOverflowPolicy(org.apache.cassandra.schema.TableMetadata, int, boolean)},
     * so if the request was not denied it means its expiration date should be capped.
     *
     * See CASSANDRA-14092
     */
    public static long computeLocalExpirationTime(long nowInSec, int timeToLive)
    {

View on GitHub (pinned to 88fd0f6a0e)