{"id":"2440382aae3f1ad2","repo":"redis/redis-py","slug":"eviction-policy-should-be-associated-with-valid-ca","errorCode":null,"errorMessage":"Eviction policy should be associated with valid cache.","messagePattern":"Eviction policy should be associated with valid cache\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"redis/cache.py","lineNumber":349,"sourceCode":"        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 = [\n        \"BITCOUNT\",\n        \"BITFIELD_RO\",\n        \"BITPOS\",\n        \"EXISTS\",\n        \"GEODIST\",\n        \"GEOHASH\",","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/cache.py#L331-L367","documentation":"Raised as ValueError by LRUPolicy._assert_cache (redis/cache.py:349) when self.cache is None or is not a CacheInterface instance. The eviction policy must be attached to a cache before any eviction/touch operation; using it standalone (or before the Cache wires it up) violates that contract.","triggerScenarios":"Constructing an LRUPolicy and calling evict_next/evict_many/touch before associating it with a cache; manually creating a policy that bypasses CacheConfig's wiring; cache setter never invoked.","commonSituations":"Directly instantiating LRUPolicy for testing without binding a cache; refactor that decoupled policy from cache; misuse of the internal API.","solutions":["Obtain the eviction policy via CacheConfig/EvictionPolicy rather than instantiating LRUPolicy directly.","If you do construct LRUPolicy manually, set policy.cache = <a CacheInterface instance> before any operation.","Ensure the Cache object assigns itself to its policy during construction."],"exampleFix":"# before\npolicy = LRUPolicy()\npolicy.evict_next()  # ValueError: not associated\n# after\npolicy = LRUPolicy()\npolicy.cache = DefaultCache(config=CacheConfig())\npolicy.evict_next()","handlingStrategy":"validation","validationCode":"from redis.cache import CacheInterface\nif getattr(policy, 'cache', None) is None or not isinstance(policy.cache, CacheInterface):\n    policy.cache = DefaultCache(config=CacheConfig())","typeGuard":"def policy_attached(policy) -> bool:\n    from redis.cache import CacheInterface\n    return isinstance(getattr(policy, 'cache', None), CacheInterface)","tryCatchPattern":"try:\n    policy.evict_next()\nexcept ValueError as e:\n    raise ConfigError('eviction policy not wired to a cache') from e","preventionTips":["Obtain policies via CacheConfig rather than raw LRUPolicy().","Always set policy.cache before any operation in tests."],"tags":["cache","config","validation"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}