{"id":"76b26301f4b0ca8f","repo":"redis/redis-py","slug":"item-not-found","errorCode":null,"errorMessage":"Item not found","messagePattern":"Item not found","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"redis/data_structure.py","lineNumber":39,"sourceCode":"            # Find insertion point using binary search\n            left, right = 0, len(self._items)\n            while left < right:\n                mid = (left + right) // 2\n                if self._items[mid][1] < weight:\n                    right = mid\n                else:\n                    left = mid + 1\n\n            self._items.insert(left, (item, weight))\n\n    def remove(self, item):\n        \"\"\"Remove first occurrence of item\"\"\"\n        with self._lock:\n            for i, (stored_item, weight) in enumerate(self._items):\n                if stored_item == item:\n                    self._items.pop(i)\n                    return weight\n            raise ValueError(\"Item not found\")\n\n    def get_by_weight_range(\n        self, min_weight: float, max_weight: float\n    ) -> List[tuple[Any, Number]]:\n        \"\"\"Get all items within weight range\"\"\"\n        with self._lock:\n            result = []\n            for item, weight in self._items:\n                if min_weight <= weight <= max_weight:\n                    result.append((item, weight))\n            return result\n\n    def get_top_n(self, n: int) -> List[tuple[Any, Number]]:\n        \"\"\"Get top N the highest weighted items\"\"\"\n        with self._lock:\n            return [(item, weight) for item, weight in self._items[:n]]\n\n    def update_weight(self, item, new_weight: float):","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/data_structure.py#L21-L57","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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()."],"exampleFix":"// before\ndatabases.remove((db, weight))  # ValueError if not present\n\n// after\ntry:\n    databases.remove((db, weight))\nexcept ValueError:\n    pass  # already removed, nothing to do","handlingStrategy":"validation","validationCode":"from redis.data_structure import WeightedList\nwl = WeightedList()\nwl.add(db, 1.0)\n# WeightedList has no __contains__; snapshot before removing\npresent = any(item == db for item, _ in wl)\nif present:\n    wl.remove(db)","typeGuard":"from redis.data_structure import WeightedList\n\ndef safe_remove(wl: WeightedList, item) -> bool:\n    for stored, _ in wl:\n        if stored == item:\n            wl.remove(item)\n            return True\n    return False","tryCatchPattern":"try:\n    wl.remove(item)\nexcept ValueError:\n    pass  # already absent; treat as no-op","preventionTips":["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."],"tags":["data-structure","multidb","failover","valueerror"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}