redis/redis-py · error · ValueError

Eviction policy should be associated with valid cache.

Error message

Eviction policy should be associated with valid cache.

What it means

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.

Source

Thrown at redis/cache.py:349

        popped_keys = []

        for _ in range(count):
            popped_entry = self._cache.collection.popitem(last=False)
            popped_keys.append(popped_entry[0])

        return popped_keys

    def touch(self, cache_key: CacheKey) -> None:
        self._assert_cache()

        if self._cache.collection.get(cache_key) is None:
            raise ValueError("Given entry does not belong to the cache")

        self._cache.collection.move_to_end(cache_key)

    def _assert_cache(self):
        if self.cache is None or not isinstance(self.cache, CacheInterface):
            raise ValueError("Eviction policy should be associated with valid cache.")


class EvictionPolicy(Enum):
    LRU = LRUPolicy


class CacheConfig(CacheConfigurationInterface):
    DEFAULT_CACHE_CLASS = DefaultCache
    DEFAULT_EVICTION_POLICY = EvictionPolicy.LRU
    DEFAULT_MAX_SIZE = 10000

    DEFAULT_ALLOW_LIST = [
        "BITCOUNT",
        "BITFIELD_RO",
        "BITPOS",
        "EXISTS",
        "GEODIST",
        "GEOHASH",

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Obtain the eviction policy via CacheConfig/EvictionPolicy rather than instantiating LRUPolicy directly.
  2. If you do construct LRUPolicy manually, set policy.cache = <a CacheInterface instance> before any operation.
  3. Ensure the Cache object assigns itself to its policy during construction.

Example fix

# before
policy = LRUPolicy()
policy.evict_next()  # ValueError: not associated
# after
policy = LRUPolicy()
policy.cache = DefaultCache(config=CacheConfig())
policy.evict_next()
Defensive patterns

Strategy: validation

Validate before calling

from redis.cache import CacheInterface
if getattr(policy, 'cache', None) is None or not isinstance(policy.cache, CacheInterface):
    policy.cache = DefaultCache(config=CacheConfig())

Type guard

def policy_attached(policy) -> bool:
    from redis.cache import CacheInterface
    return isinstance(getattr(policy, 'cache', None), CacheInterface)

Try / catch

try:
    policy.evict_next()
except ValueError as e:
    raise ConfigError('eviction policy not wired to a cache') from e

Prevention

When it happens

Trigger: 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.

Common situations: Directly instantiating LRUPolicy for testing without binding a cache; refactor that decoupled policy from cache; misuse of the internal API.

Related errors


AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04). Data as JSON: /data/errors/2440382aae3f1ad2.json. Report an issue: GitHub.