From fa24f4ee6047951abe503bb52e3e602be992944a Mon Sep 17 00:00:00 2001 From: Deep Mehta Date: Thu, 12 Mar 2026 20:47:40 -0700 Subject: [PATCH] fix: gate provider lookups to outputs cache and fix UI coercion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add `enable_providers` flag to BasicCache so only the outputs cache triggers external provider lookups/stores. The objects cache stores node class instances, not CacheEntry values, so provider calls were wasted round-trips that always missed. - Remove `or {}` coercion on `result.ui` — an empty dict passes the `is not None` gate in execution.py and causes KeyError when the history builder indexes `["output"]` and `["meta"]`. Preserving `None` correctly skips the ui_node_outputs addition. Co-Authored-By: Claude Opus 4.6 --- comfy_execution/caching.py | 21 +++++++++++++-------- execution.py | 6 +++--- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/comfy_execution/caching.py b/comfy_execution/caching.py index 750bddf2e..78212bde3 100644 --- a/comfy_execution/caching.py +++ b/comfy_execution/caching.py @@ -148,9 +148,10 @@ class CacheKeySetInputSignature(CacheKeySet): self.get_ordered_ancestry_internal(dynprompt, ancestor_id, ancestors, order_mapping) class BasicCache: - def __init__(self, key_class): + def __init__(self, key_class, enable_providers=False): self.key_class = key_class self.initialized = False + self.enable_providers = enable_providers self.dynprompt: DynamicPrompt self.cache_key_set: CacheKeySet self.cache = {} @@ -239,6 +240,8 @@ class BasicCache: CacheValue, _contains_self_unequal, _logger ) + if not self.enable_providers: + return if not _has_cache_providers(): return if not self._is_external_cacheable_value(value): @@ -274,6 +277,8 @@ class BasicCache: CacheValue, _contains_self_unequal, _logger ) + if not self.enable_providers: + return None if not _has_cache_providers(): return None if _contains_self_unequal(cache_key): @@ -296,7 +301,7 @@ class BasicCache: _logger.warning(f"Provider {provider.__class__.__name__} returned invalid outputs") continue from execution import CacheEntry - return CacheEntry(ui=result.ui or {}, outputs=list(result.outputs)) + return CacheEntry(ui=result.ui, outputs=list(result.outputs)) except Exception as e: _logger.warning(f"Cache provider {provider.__class__.__name__} error on lookup: {e}") @@ -354,8 +359,8 @@ class BasicCache: return result class HierarchicalCache(BasicCache): - def __init__(self, key_class): - super().__init__(key_class) + def __init__(self, key_class, enable_providers=False): + super().__init__(key_class, enable_providers=enable_providers) def _get_cache_for(self, node_id): assert self.dynprompt is not None @@ -432,8 +437,8 @@ class NullCache: return self class LRUCache(BasicCache): - def __init__(self, key_class, max_size=100): - super().__init__(key_class) + def __init__(self, key_class, max_size=100, enable_providers=False): + super().__init__(key_class, enable_providers=enable_providers) self.max_size = max_size self.min_generation = 0 self.generation = 0 @@ -501,8 +506,8 @@ RAM_CACHE_OLD_WORKFLOW_OOM_MULTIPLIER = 1.3 class RAMPressureCache(LRUCache): - def __init__(self, key_class): - super().__init__(key_class, 0) + def __init__(self, key_class, enable_providers=False): + super().__init__(key_class, 0, enable_providers=enable_providers) self.timestamps = {} def clean_unused(self): diff --git a/execution.py b/execution.py index a8e8fc59f..1a6c3429c 100644 --- a/execution.py +++ b/execution.py @@ -127,15 +127,15 @@ class CacheSet: # Performs like the old cache -- dump data ASAP def init_classic_cache(self): - self.outputs = HierarchicalCache(CacheKeySetInputSignature) + self.outputs = HierarchicalCache(CacheKeySetInputSignature, enable_providers=True) self.objects = HierarchicalCache(CacheKeySetID) def init_lru_cache(self, cache_size): - self.outputs = LRUCache(CacheKeySetInputSignature, max_size=cache_size) + self.outputs = LRUCache(CacheKeySetInputSignature, max_size=cache_size, enable_providers=True) self.objects = HierarchicalCache(CacheKeySetID) def init_ram_cache(self, min_headroom): - self.outputs = RAMPressureCache(CacheKeySetInputSignature) + self.outputs = RAMPressureCache(CacheKeySetInputSignature, enable_providers=True) self.objects = HierarchicalCache(CacheKeySetID) def init_null_cache(self):