{"id":"ae9e8010bc4b29a1","repo":"redis/redis-py","slug":"given-entry-does-not-belong-to-the-cache","errorCode":null,"errorMessage":"Given entry does not belong to the cache","messagePattern":"Given entry does not belong to the cache","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"redis/cache.py","lineNumber":343,"sourceCode":"\n    def evict_many(self, count: int) -> List[CacheKey]:\n        self._assert_cache()\n        if count > len(self._cache.collection):\n            raise ValueError(\"Evictions count is above cache size\")\n\n        popped_keys = []\n\n        for _ in range(count):\n            popped_entry = self._cache.collection.popitem(last=False)\n            popped_keys.append(popped_entry[0])\n\n        return popped_keys\n\n    def touch(self, cache_key: CacheKey) -> None:\n        self._assert_cache()\n\n        if self._cache.collection.get(cache_key) is None:\n            raise ValueError(\"Given entry does not belong to the cache\")\n\n        self._cache.collection.move_to_end(cache_key)\n\n    def _assert_cache(self):\n        if self.cache is None or not isinstance(self.cache, CacheInterface):\n            raise ValueError(\"Eviction policy should be associated with valid cache.\")\n\n\nclass EvictionPolicy(Enum):\n    LRU = LRUPolicy\n\n\nclass CacheConfig(CacheConfigurationInterface):\n    DEFAULT_CACHE_CLASS = DefaultCache\n    DEFAULT_EVICTION_POLICY = EvictionPolicy.LRU\n    DEFAULT_MAX_SIZE = 10000\n\n    DEFAULT_ALLOW_LIST = [","sourceCodeStart":325,"sourceCodeEnd":361,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/cache.py#L325-L361","documentation":"Raised as ValueError by LRUPolicy.touch (redis/cache.py:343) when the given cache_key is not present in the collection. touch() is meant to mark an existing LRU entry as most-recently-used (via move_to_end), so touching a key that was never inserted or has been evicted is rejected.","triggerScenarios":"Calling policy.touch(k) for a key that was never added, or that was already evicted; touch invoked on a stale key reference after the cache was pruned.","commonSituations":"Touching a key whose entry expired/evicted between read and touch; logic that touches keys without confirming membership; concurrent eviction removing the entry first.","solutions":["Check membership (cache_key in cache.collection) before calling touch.","Only touch keys you just inserted or confirmed present.","Catch the ValueError and treat as a no-op / re-insert if the key should still be cached."],"exampleFix":"# before\npolicy.touch(maybe_stale_key)  # ValueError if absent\n# after\nif maybe_stale_key in cache.collection:\n    policy.touch(maybe_stale_key)","handlingStrategy":"validation","validationCode":"if cache_key in cache.collection:\n    policy.touch(cache_key)","typeGuard":"def key_in_cache(cache, key) -> bool:\n    return key in cache.collection","tryCatchPattern":"try:\n    policy.touch(cache_key)\nexcept ValueError:\n    pass  # already evicted; nothing to touch","preventionTips":["Confirm membership before touching.","Treat a touch miss as a no-op."],"tags":["cache","validation"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}