{"record":{"id":"33a993957f4fff25","repo":"TheAlgorithms/Java","slug":"ttl-must-be-0-33a993","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/LIFOCache.java","lineNumber":175,"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 removed, re-inserted at tail and its TTL is reset.\n     * If the key does not exist and the cache is full, the youngest 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 key already exists, remove it. It will later be re-inserted at top of stack\n            keys.remove(key);\n            final CacheEntry<V> oldEntry = cache.remove(key);\n            if (oldEntry != null && !oldEntry.isExpired()) {\n                notifyEviction(key, oldEntry.value);\n            }\n\n            // Evict expired entries to make space for new entry\n            evictExpired();\n\n            // If no expired entry was removed, remove the youngest\n            if (cache.size() >= capacity) {\n                final K youngestKey = keys.pollLast();\n                final CacheEntry<V> youngestEntry = cache.remove(youngestKey);","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/TheAlgorithms/Java/blob/fdfb9a395b310167a66bd29e311e36e0e3e9b964/src/main/java/com/thealgorithms/datastructures/caches/LIFOCache.java#L157-L193","documentation":"Thrown by LIFOCache.put(K, V, long ttlMillis) when ttlMillis is negative. Expiry is computed as now + ttlMillis, so a negative TTL sets expiry in the past and makes the entry instantly invalid. The check runs after the null guard, before lock acquisition.","triggerScenarios":"cache.put(k, v, -1); ttlMillis from a negative Duration.toMillis(); clock-skew arithmetic yielding a negative delta; config typo with a leading minus.","commonSituations":"TTL from request headers with bad client clocks; env config (cache.ttl=-5000) typoed; reused duration variable inverted elsewhere.","solutions":["Clamp the TTL: long ttl = Math.max(0, ttlMillis);","Treat negative TTL as 'no expiry' or 'skip caching' per your domain, explicitly.","Validate all TTL config keys at startup."],"exampleFix":"// before\ncache.put(k, v, duration.toMillis());\n// after\nlong ttl = duration.toMillis();\nif (ttl < 0) throw new IllegalStateException(\"negative ttl: \" + duration);\ncache.put(k, v, ttl);","handlingStrategy":"validation","validationCode":"long ttl = Math.max(0, ttlMillis);\ncache.put(key, value, ttl);","typeGuard":"static boolean isValidTtl(long ttlMillis) {\n    return ttlMillis >= 0;\n}","tryCatchPattern":null,"preventionTips":["Validate TTL config at startup.","Assert Duration is non-negative before converting to millis.","Watch for clock-skew arithmetic that inverts the delta."],"tags":["java","lifo-cache","ttl","argument-validation","cache"],"backgroundTag":null,"analyzedSha":"fdfb9a395b310167a66bd29e311e36e0e3e9b964","analyzedAt":"2026-08-13T23:36:13.315Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}