TheAlgorithms/Java · error · IllegalArgumentException
Default TTL must be >= 0
Error message
Default TTL must be >= 0
What it means
Thrown by FIFOCache.Builder.defaultTTL(long) when ttlMillis is negative. The default TTL is applied to entries added without an explicit TTL; a negative value would set every such entry's expiry in the past. The check runs before storing the field and returns this for chaining, so the builder remains valid on rejection (the exception propagates first).
Source
Thrown at src/main/java/com/thealgorithms/datastructures/caches/FIFOCache.java:504
* @throws IllegalArgumentException if {@code capacity} is less than or equal to 0
*/
public Builder(int capacity) {
if (capacity <= 0) {
throw new IllegalArgumentException("Capacity must be > 0");
}
this.capacity = capacity;
}
/**
* Sets the default time-to-live (TTL) in milliseconds for cache entries.
*
* @param ttlMillis the TTL duration in milliseconds; must be >= 0
* @return this builder instance for chaining
* @throws IllegalArgumentException if {@code ttlMillis} is negative
*/
public Builder<K, V> defaultTTL(long ttlMillis) {
if (ttlMillis < 0) {
throw new IllegalArgumentException("Default TTL must be >= 0");
}
this.defaultTTL = ttlMillis;
return this;
}
/**
* Sets an eviction listener to be notified when entries are evicted from the cache.
*
* @param listener a {@link BiConsumer} that accepts evicted keys and values; must not be {@code null}
* @return this builder instance for chaining
* @throws IllegalArgumentException if {@code listener} is {@code null}
*/
public Builder<K, V> evictionListener(BiConsumer<K, V> listener) {
if (listener == null) {
throw new IllegalArgumentException("Listener must not be null");
}
this.evictionListener = listener;
return this;View on GitHub (pinned to fdfb9a395b)
Solutions
- Clamp the value: builder.defaultTTL(Math.max(0, configuredTtl)).
- Treat negative config as 'use 0 (no expiry)' explicitly, or reject the config at startup.
- Add a startup assertion on all TTL config keys.
Example fix
// before builder.defaultTTL(props.getTtlMillis()); // after long ttl = props.getTtlMillis(); builder.defaultTTL(ttl < 0 ? 0 : ttl);
Defensive patterns
Strategy: validation
Validate before calling
long ttl = configuredDefaultTtl; builder.defaultTTL(ttl < 0 ? 0 : ttl);
Type guard
static boolean isValidDefaultTtl(long ttlMillis) {
return ttlMillis >= 0;
} Prevention
- Clamp negative config to 0 (no expiry) explicitly, or reject at startup.
- Add startup assertions for all TTL config keys.
- Beware Duration negation and clock-skew arithmetic.
When it happens
Trigger: builder.defaultTTL(-1); defaultTTL(parsed from a negative Duration); config typo with a leading minus; TTL computed from inverted timestamps.
Common situations: Environment config (e.g. cache.defaultTtl=-60000) typoed; duration derived from clock skew; reusing a variable that was negated for a different purpose.
Related errors
- TTL must be >= 0
- Capacity must be > 0
- Listener must not be null
- Eviction strategy must not be null
- Default TTL must be >= 0
AI-assisted analysis of TheAlgorithms/Java@fdfb9a395b (2026-08-13).
Data as JSON: /api/errors/ae0c94257f395190.
Report an issue: GitHub.