{"record":{"id":"fd79adf77e92289a","repo":"TheAlgorithms/Java","slug":"cache-cannot-be-empty-fd79ad","errorCode":null,"errorMessage":"Cache cannot be empty!","messagePattern":"Cache cannot be empty!","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/main/java/com/thealgorithms/datastructures/caches/MRUCache.java","lineNumber":78,"sourceCode":"     *\n     * @param capacity the capacity to check\n     * @throws IllegalArgumentException if the capacity is less than or equal to zero\n     */\n    private void checkCapacity(int capacity) {\n        if (capacity <= 0) {\n            throw new IllegalArgumentException(\"Capacity must be greater than 0!\");\n        }\n    }\n\n    /**\n     * Evicts the most recently used entry from the cache.\n     *\n     * @return the evicted entry\n     * @throws RuntimeException if the cache is empty\n     */\n    private Entry<K, V> evict() {\n        if (head == null) {\n            throw new RuntimeException(\"Cache cannot be empty!\");\n        }\n        final Entry<K, V> evicted = this.tail;\n        tail = evicted.getPreEntry();\n        if (tail != null) {\n            tail.setNextEntry(null);\n        }\n        evicted.setNextEntry(null);\n        return evicted;\n    }\n\n    /**\n     * Retrieves the value associated with the specified key.\n     *\n     * @param key the key whose associated value is to be returned\n     * @return the value associated with the specified key, or null if the key does not exist\n     */\n    public V get(K key) {\n        if (!data.containsKey(key)) {","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/TheAlgorithms/Java/blob/fdfb9a395b310167a66bd29e311e36e0e3e9b964/src/main/java/com/thealgorithms/datastructures/caches/MRUCache.java#L60-L96","documentation":"Internal assertion inside MRUCache's private evict() method. Fires when the most-recently-used entry (tail) is to be evicted but head is null, indicating the linked list is empty. In correct single-threaded operation the caller logic prevents calling evict() on an empty list. Hitting this signals concurrent access on this explicitly thread-unsafe class or a library bug.","triggerScenarios":"Two or more threads simultaneously calling put() on the same MRUCache without external synchronization. The unsynchronized HashMap and linked-list pointers can desynchronize so that data.size() == cap is true while head is null, causing evict() to fail.","commonSituations":"Using MRUCache as a shared cache in a servlet, actor system, or thread pool without wrapping it in a lock. Assuming thread-safety that the class does not provide.","solutions":["Synchronize all access to the MRUCache instance with an external lock","Switch to a purpose-built thread-safe cache (Caffeine, Guava)","If single-threaded and still triggering it, report a library bug with a minimal reproducer"],"exampleFix":"// before — unsynchronized shared MRUCache\nMRUCache<String,byte[]> cache = new MRUCache<>(50);\n// concurrent put() calls can corrupt state\n\n// after — guard with a lock\nMRUCache<String,byte[]> cache = new MRUCache<>(50);\nprivate final ReentrantLock lock = new ReentrantLock();\npublic void safePut(String k, byte[] v) {\n    lock.lock();\n    try { cache.put(k, v); } finally { lock.unlock(); }\n}","handlingStrategy":"validation","validationCode":"// Prevent concurrent access to the thread-unsafe MRUCache.\nprivate final ReentrantLock mruLock = new ReentrantLock();\nvoid safePut(MRUCache<K,V> cache, K k, V v) {\n    mruLock.lock();\n    try { cache.put(k, v); } finally { mruLock.unlock(); }\n}","typeGuard":null,"tryCatchPattern":"try {\n    cache.put(key, val);\n} catch (RuntimeException e) {\n    if (\"Cache cannot be empty!\".equals(e.getMessage())) {\n        cache = new MRUCache<>(cap); // rebuild corrupted state\n    } else throw e;\n}","preventionTips":["Never share MRUCache across threads without synchronization","Use a dedicated lock object per cache instance","Switch to Caffeine or Guava for shared concurrent caches"],"tags":["mru-cache","concurrency","thread-safety","data-structures"],"backgroundTag":null,"analyzedSha":"fdfb9a395b310167a66bd29e311e36e0e3e9b964","analyzedAt":"2026-08-13T23:36:13.315Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}