redis/redis-py · warning · ValueError
Item not found
Error message
Item not found
What it means
Raised as ValueError by WeightedList.remove (redis/data_structure.py:39) when the item being removed is not present in the list. WeightedList is the thread-safe priority list used internally by the Active-Active multidb client (redis/multidb/) to rank databases by weight and drive failover. remove() returns silently only if it finds the item; otherwise it raises.
Source
Thrown at redis/data_structure.py:39
# Find insertion point using binary search
left, right = 0, len(self._items)
while left < right:
mid = (left + right) // 2
if self._items[mid][1] < weight:
right = mid
else:
left = mid + 1
self._items.insert(left, (item, weight))
def remove(self, item):
"""Remove first occurrence of item"""
with self._lock:
for i, (stored_item, weight) in enumerate(self._items):
if stored_item == item:
self._items.pop(i)
return weight
raise ValueError("Item not found")
def get_by_weight_range(
self, min_weight: float, max_weight: float
) -> List[tuple[Any, Number]]:
"""Get all items within weight range"""
with self._lock:
result = []
for item, weight in self._items:
if min_weight <= weight <= max_weight:
result.append((item, weight))
return result
def get_top_n(self, n: int) -> List[tuple[Any, Number]]:
"""Get top N the highest weighted items"""
with self._lock:
return [(item, weight) for item, weight in self._items[:n]]
def update_weight(self, item, new_weight: float):View on GitHub (pinned to da03cdc7e8)
Solutions
- Guard the removal: iterate or snapshot the list to confirm the item exists before calling remove().
- Wrap remove() in try/except ValueError and treat 'not found' as a no-op if double-removal is acceptable in your flow.
- For the multidb client, remove each database exactly once and avoid mutating the configuration concurrently.
- Track add/remove symmetry in your own code so every remove() has a matching prior add().
Example fix
// before
databases.remove((db, weight)) # ValueError if not present
// after
try:
databases.remove((db, weight))
except ValueError:
pass # already removed, nothing to do Defensive patterns
Strategy: validation
Validate before calling
from redis.data_structure import WeightedList
wl = WeightedList()
wl.add(db, 1.0)
# WeightedList has no __contains__; snapshot before removing
present = any(item == db for item, _ in wl)
if present:
wl.remove(db) Type guard
from redis.data_structure import WeightedList
def safe_remove(wl: WeightedList, item) -> bool:
for stored, _ in wl:
if stored == item:
wl.remove(item)
return True
return False Try / catch
try:
wl.remove(item)
except ValueError:
pass # already absent; treat as no-op Prevention
- For the multidb client, remove each database exactly once.
- Avoid mutating the multidb configuration concurrently from multiple threads.
- Wrap remove() calls so an absent item is a benign no-op rather than a crash.
- Keep add/remove operations symmetric and tracked in your own state.
When it happens
Trigger: Calling WeightedList.remove(item) (directly, or via the multidb client removing a database that was never added or was already removed) for an item whose value is not currently stored.
Common situations: Removing a database from the multidb client twice; removing a database whose weight tuple changed identity so equality no longer matches; concurrent remove of the same entry racing in two threads (the second finds nothing).
Related errors
- Initial connection failed - no active database found
- Cannot set active database, database is unhealthy
- No valid database available for communication
- No database connections currently available. This is a tempo
- Given database is not a member of database list
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/76b26301f4b0ca8f.json.
Report an issue: GitHub.