redis/redis-py · warning · ValueError

Evictions count is above cache size

Error message

Evictions count is above cache size

What it means

Raised as ValueError in LRUPolicy.evict_many when the requested count exceeds the number of entries currently in the cache collection. evict_many pops count items via popitem; asking for more than exist would underflow the ordered dict, so it validates up front.

Solutions

  1. Clamp the count to the current cache size before calling evict_many: count = min(count, cache.size).
  2. Use evict_next() in a loop if you need best-effort eviction up to a limit.
  3. Re-check cache.size immediately before eviction to avoid stale counts.

Example fix

# before
keys = policy.evict_many(requested_count)  # may exceed size
# after
keys = policy.evict_many(min(requested_count, cache.size))
Defensive patterns

Strategy: validation

Validate before calling

count = min(count, cache.size)
keys = policy.evict_many(count)

Try / catch

try:
    keys = policy.evict_many(count)
except ValueError as e:
    if "above cache size" in str(e):
        keys = policy.evict_many(cache.size)
    else:
        raise

Prevention

When it happens

Trigger: Calling eviction_policy.evict_many(n) with n greater than len(cache.collection). This is an internal client-side-caching (CSC) path; evict_many is invoked by cache management code when evicting batches.

Common situations: A bug in cache management computing an eviction count from a stale size. Calling evict_many right after a flush or on a nearly-empty cache. Misuse of the eviction policy API directly with an oversized count.

Related errors


AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10). Data as JSON: /api/errors/2a46dae3b213076c. Report an issue: GitHub.

Appendix: source

Thrown at redis/cache.py:329

        return self._cache

    @cache.setter
    def cache(self, cache: CacheInterface):
        self._cache = cache

    @property
    def type(self) -> EvictionPolicyType:
        return EvictionPolicyType.time_based

    def evict_next(self) -> CacheKey:
        self._assert_cache()
        popped_entry = self._cache.collection.popitem(last=False)
        return popped_entry[0]

    def evict_many(self, count: int) -> List[CacheKey]:
        self._assert_cache()
        if count > len(self._cache.collection):
            raise ValueError("Evictions count is above cache size")

        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):

View on GitHub (pinned to 6a6b581b48)