             for key in keys {
                 let nsKey = key as NSString
                 guard let object = storage.object(forKey: nsKey) else {
+                    // This could happen if the object is moved by cache `totalCostLimit` or `countLimit` rule.
+                    // We didn't remove the key yet until now, since we do not want to introduce additonal lock.
+                    // See https://github.com/onevcat/Kingfisher/issues/1233
                     keys.remove(key)
                     continue
                 }

            self.config = config
            storage.totalCostLimit = config.totalCostLimit
            storage.countLimit = config.countLimit
            storage.delegate = cacheDelegate
            cacheDelegate.onObjectRemoved.delegate(on: self) { (self, obj) in
                self.keys.remove(obj.key)
            }

            cleanTimer = .scheduledTimer(withTimeInterval: config.cleanInterval, repeats: true) { [weak self] _ in
                guard let self = self else { return }

            storage.removeAllObjects()
            keys.removeAll()
        }
    }
}

