MutaFix run: boltons-004
ranker nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B · patcher nvidia/nemotron-3-super-120b-a12b · via Nebius Token Factory
- if not (not self.on_miss): (injected bug)+ if not self.on_miss: (original)retriever rank 1 of 20 · ranker position 1 · patched the right function yes · exact restore yes
Trace
failing tests and errors
tests/test_cacheutils.py::test_lru_basic tests/test_cacheutils.py::test_cached_dec tests/test_cacheutils.py::test_unscoped_cached_dec tests/test_cacheutils.py::test_callable_cached_dec tests/test_cacheutils.py::test_cachedmethodtests/test_cacheutils.py::test_lru_basic
E KeyError: 'hi' E TypeError: 'NoneType' object is not callabletests/test_cacheutils.py::test_cached_dec
E KeyError: _HashedKey([]) E TypeError: 'NoneType' object is not callable
tests/test_cacheutils.py::test_lru_basic in the static call graph. Kept 20 candidates, ranked by spectrum score (Ochiai), call graph and BM25 break ties.candidates in retriever order
boltons/cacheutils.py::LRU.__getitem__boltons/cacheutils.py::make_cache_keyboltons/cacheutils.py::CachedFunction.__init__boltons/cacheutils.py::_HashedKey.__init__boltons/cacheutils.py::cachedboltons/cacheutils.py::CachedFunction.__call__boltons/cacheutils.py::cached.<locals>.cached_func_decoratorboltons/cacheutils.py::_HashedKey.__hash__boltons/cacheutils.py::CachedFunction.__init__.<locals>._get_cacheboltons/cacheutils.py::_HashedKey.__repr__boltons/cacheutils.py::LRI._get_link_and_move_to_front_of_llboltons/cacheutils.py::LRI._init_llboltons/cacheutils.py::LRI.__init__boltons/cacheutils.py::LRI.getboltons/cacheutils.py::LRI.__repr__boltons/cacheutils.py::CachedMethod.__call__boltons/cacheutils.py::CachedMethod.__get__boltons/cacheutils.py::CachedMethod.__init__boltons/cacheutils.py::cachedmethodboltons/cacheutils.py::cachedmethod.<locals>.cached_method_decorator
boltons/cacheutils.py::LRU.__getitem__boltons/cacheutils.py::make_cache_keyboltons/cacheutils.py::CachedFunction.__init__boltons/cacheutils.py::_HashedKey.__init__boltons/cacheutils.py::cached
read boltons/cacheutils.py::LRI._get_link_and_move_to_front_of_ll
The failing tests show KeyError and TypeError related to missing keys and NoneType being called, which suggests the LRU implementation's internal link handling is broken. Candidate 11 (LRI._get_link_and_move_to_front_of_ll) is the core method that retrieves and moves nodes in the linked list, and it's the only one that appears in all 5 failing tests. The error messages indicate that keys like 'hi' and _HashedKey([]) are not found, which aligns with a faulty link lookup mechanism.
The KeyError in the failing tests occurs because self._link_lookup[key] is accessed without checking if the key exists. The tests expect a KeyError to be raised for missing keys, but the current code would raise a KeyError from the dictionary lookup anyway. However, the actual bug is that the method assumes the key exists and directly uses it, but the error messages show that the KeyError is being raised from the test's expectation, not from the code. The fix is to explicitly check for key existence and raise KeyError if missing, which matches the expected behavior in the tests.
--- a/boltons/cacheutils.py+++ b/boltons/cacheutils.py@@ -168,4 +168,6 @@ # find what will become the newest link. this may raise a # KeyError, which is useful to __getitem__ and __setitem__+ if key not in self._link_lookup:+ raise KeyError(key) newest = self._link_lookup[key]
tests: 5 failing (target tests)
tests/test_cacheutils.py::test_lru_basic tests/test_cacheutils.py::test_cached_dec tests/test_cacheutils.py::test_unscoped_cached_dec tests/test_cacheutils.py::test_callable_cached_dec tests/test_cacheutils.py::test_cachedmethod
read boltons/cacheutils.py::CachedFunction.__call__
CachedFunction.__call__ is the actual wrapper that gets called when the decorated function is invoked. It likely uses self.get_cache and self.key_func to compute the key and then retrieve from cache. If on_miss is None, that could come from the cache's miss handler. The TypeError about NoneType being callable suggests that somewhere a None is being called as a function, possibly the on_miss attribute of the cache (like LRU) is None.
model reasoning (excerpt)
We need to look at other candidates. The errors include both KeyError and TypeError about NoneType being callable. That suggests something is returning None where a callable is expected. Look at candidate 1: LRU.__getitem__. It calls self.on_miss(key) and assigns self[key] = self.on_miss(key). If on_miss is None, then calling it would cause TypeError: 'NoneType' object is not callable. Indeed, the error shows that. So maybe on_miss is None when it shouldn't be. Let's examine LRU class initialization. But we haven't seen LRU.__init__. Let's check candidate? Not in top list. We can read LRU class. Let's read the LRU class definition (maybe it's earlier in the file). We'll do a read on the file around the LRU class. But we can only read candidates. However we can request to read a specific function by number? The system only allows reading candidates by their index in the list. We have not seen LRU.__init__ in the candidates. But we can ask to read the file? No, only candidate functions. However we can ask to read a candidate that is not in the list? The instruction says: "Candidate functions, ranked by a fault-localization model (most likely first):" and then lists 20. We can only read those. But we can ask to read any of those 20. We need to find where on_miss is set. Look at candidate 1: LRU.__getitem__ references self.on_miss. Where is on_miss defined? Probably in LRU.__init__. Let's see if LRU.__init__ is in the candidates. It is not listed. But we can look at nearby can
read boltons/cacheutils.py::LRU.__getitem__
Looking at LRU.__getitem__, we see it handles KeyError by incrementing miss_count and then conditionally calling self.on_miss(key). The TypeError 'NoneType' object is not callable indicates that self.on_miss is None when it's being called. This happens in line 373: ret = self[key] = self.on_miss(key). We need to check why on_miss is None and ensure it's only called when it's actually set.
model reasoning (excerpt)
We have two issues from the test failures: 1. KeyError: 'hi' (or other keys) - meaning the key is not found in the cache when it should be. 2. TypeError: 'NoneType' object is not callable - meaning something that is None is being called. Looking at the CachedFunction.__call__ (candidate 6), we see: 462 | cache = self.get_cache() 463 | key = self.key_func(args, kwargs, typed=self.typed) 464 | try: 465 | ret = cache[key] 466 | except KeyError: 467 | ret = cache[key] = self.func(*args, **kwargs) 468 | return ret If the key is not in the cache, we call self.func and store the result. However, note that the cache might be an LRU instance that has an on_miss callback. But in the CachedFunction, we are not using the cache's on_miss; we are directly calling self.func and setting the cache. But wait: the LRU class (from candidate 1) has an on_miss attribute. In the LRU.__getitem__ (candidate 1), we see: 365 | def __getitem__(self, key): 366 | with self._lock: 367 | try: 368 | link = self._get_link_and_move_to_front_of_ll(key) 369 | except KeyError: 370 | self.miss_count += 1 371 | if not (not self.on_miss): 372 | raise 373 | ret = self[key] = self.on_miss(key) 374 | return ret 375 | 376 | self.hit_count += 1 377 | ret
The condition in LRU.__getitem__ was backwards: it raised KeyError when on_miss was truthy and tried to call on_miss when it was falsy (often None), causing the TypeError. The fix inverts the condition so that KeyError is raised only when on_miss is falsy (missing), and on_miss is called only when truthy (present).
--- a/boltons/cacheutils.py+++ b/boltons/cacheutils.py@@ -369,7 +369,7 @@ except KeyError: self.miss_count += 1- if not (not self.on_miss):+ if not self.on_miss: raise- ret = self[key] = self.on_miss(key)+ ret = self[key] = self.on_miss(key) return ret
tests: all tests pass
model reasoning (excerpt)
We have identified two issues: 1. In `LRI._get_link_and_move_to_front_of_ll`, we added a check for key existence, but the tests are still failing with KeyError and TypeError. 2. In `LRU.__getitem__`, the condition `if not (not self.on_miss):` is equivalent to `if self.on_miss:`, but note that the code then does `raise` if the condition is true? Let's read carefully: Line 371: `if not (not self.on_miss):` This is double negative: `if self.on_miss:` (because `not (not x)` is `x`). Then line 372: `raise` (without argument) which re-raises the caught KeyError. So if `self.on_miss` is truthy (i.e., not None and not False), then we re-raise the KeyError. If `self.on_miss` is falsy (None or False), then we proceed to line 373: `ret = self[key] = self.on_miss(key)` But if `self.on_miss` is None, then we are trying to call None as a function, which causes the TypeError. The intended logic is probably: if there is an on_miss handler, then call it and set the value; otherwise, raise KeyError. However, the current code does the opposite: if there is an on_miss handler, it raises KeyError (by re-raising); if there isn't, it tries to call None. This is clearly backwards. Let's look at the condition again: `if not (not self.on_miss):` -> if self.on_miss is truthy, then we raise. We want: if self.on_miss is set (truthy), then we should call it and not raise. Only if it is not set (falsy) should we raise. So the condition should be: if self.on_m
Final patch
--- a/boltons/cacheutils.py+++ b/boltons/cacheutils.py@@ -369,7 +369,7 @@ except KeyError: self.miss_count += 1- if not (not self.on_miss):+ if not self.on_miss: raise- ret = self[key] = self.on_miss(key)+ ret = self[key] = self.on_miss(key) return ret