{"record":{"id":"24aef784a76a54e3","repo":"TheAlgorithms/Java","slug":"ttl-must-be-0-24aef7","errorCode":null,"errorMessage":"TTL must be >= 0","messagePattern":"TTL must be >= 0","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/com/thealgorithms/datastructures/caches/RRCache.java","lineNumber":168,"sourceCode":"    /**\n     * Adds a key-value pair to the cache with a specified time-to-live (TTL).\n     *\n     * <p>If the key already exists, its value is updated and its TTL is reset. If the key\n     * does not exist and the cache is full, a random entry is evicted to make space.\n     * Expired entries are also cleaned up prior to any eviction. The eviction listener\n     * is notified when an entry gets evicted.\n     *\n     * @param key        the key to associate with the cached value; must not be {@code null}\n     * @param value      the value to be cached; must not be {@code null}\n     * @param ttlMillis  the time-to-live for this entry in milliseconds; must be >= 0\n     * @throws IllegalArgumentException if {@code key} or {@code value} is {@code null}, or if {@code ttlMillis} is negative\n     */\n    public void put(K key, V value, long ttlMillis) {\n        if (key == null || value == null) {\n            throw new IllegalArgumentException(\"Key and value must not be null\");\n        }\n        if (ttlMillis < 0) {\n            throw new IllegalArgumentException(\"TTL must be >= 0\");\n        }\n\n        lock.lock();\n        try {\n            if (cache.containsKey(key)) {\n                cache.put(key, new CacheEntry<>(value, ttlMillis));\n                return;\n            }\n\n            evictExpired();\n\n            if (cache.size() >= capacity) {\n                int idx = random.nextInt(keys.size());\n                K evictKey = keys.remove(idx);\n                CacheEntry<V> evictVal = cache.remove(evictKey);\n                notifyEviction(evictKey, evictVal.value);\n            }\n","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/TheAlgorithms/Java/blob/fdfb9a395b310167a66bd29e311e36e0e3e9b964/src/main/java/com/thealgorithms/datastructures/caches/RRCache.java#L150-L186","documentation":"RRCache.put(key, value, ttlMillis) rejects a negative TTL. A negative TTL would set the expiry timestamp in the past, making the entry instantly expired, which is nonsensical. A TTL of 0 means no expiry (entries never expire on their own).","triggerScenarios":"Calling cache.put(key, value, -1) or any negative ttlMillis. Also triggered when the TTL is computed from a subtraction or duration conversion that produces a negative result.","commonSituations":"TTL derived from a config-specified duration that can be negative. Arithmetic on time units (e.g., subtracting a base time) that underflows. Misconfigured or missing TTL property defaulting to a sentinel like -1.","solutions":["Clamp the TTL to Math.max(0, computedTtl) before passing it","Use 0 explicitly when entries should never expire","Validate TTL configuration at startup and reject negative values with a clear message"],"exampleFix":"// before\nlong ttl = expiryEpoch - System.currentTimeMillis(); // can be negative\ncache.put(key, value, ttl);\n\n// after\nlong ttl = expiryEpoch - System.currentTimeMillis();\ncache.put(key, value, Math.max(0, ttl));","handlingStrategy":"validation","validationCode":"long safeTtl = Math.max(0, ttlMillis);\ncache.put(key, value, safeTtl);","typeGuard":null,"tryCatchPattern":"try {\n    cache.put(key, value, ttlMillis);\n} catch (IllegalArgumentException e) {\n    if (ttlMillis < 0) cache.put(key, value, 0); // retry with no-expiry\n    else throw e;\n}","preventionTips":["Clamp computed TTLs with Math.max(0, value)","Treat 0 as 'never expires' and use it as the safe default","Validate duration configs at startup"],"tags":["rr-cache","configuration","validation","ttl"],"backgroundTag":null,"analyzedSha":"fdfb9a395b310167a66bd29e311e36e0e3e9b964","analyzedAt":"2026-08-13T23:36:13.315Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}