From effb2443e7e8ff07a2430a569148933fbdc6b01b Mon Sep 17 00:00:00 2001 From: Edward Niewold Date: Sat, 25 Apr 2026 16:53:35 +0200 Subject: [PATCH] v1.2.2 - Fixed a bug where inner node validation exception were raised due to removal of initial static output slots. --- README.md | 1 + pyproject.toml | 2 +- workflow_node.py | 31 +++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b20e131..6727036 100644 --- a/README.md +++ b/README.md @@ -182,6 +182,7 @@ ComfyUI workflow JSON appears in a few different shapes depending on how it was ### Version History +- v1.2.2 - Fixed a bug where inner node validation exception were raised due to removal of initial static output slots. - v1.2.1 - Removed the maximum number of inputs and outputs on the `Subworkflow` node (was previously set to 8). - v1.2.0 - Added manual value entry for primitive `Subworkflow Input` input nodes on the `Subworkflow` node. Check README features section for details. - v1.1.0 - Added `Subworkflow Modifier`, `Subworkflow Modifier Source` (+ from URL) nodes. Combining these nodes in inner and outer workflows allows for circular links between an inner workflow input and output, without circular reference problems. diff --git a/pyproject.toml b/pyproject.toml index 5666e22..a58058c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "comfyui-subworkflow" -version = "1.2.1" +version = "1.2.2" description = "Use ComfyUI workflows as reusable subworkflows via Subworkflow Input, Subworkflow Output, and Subworkflow nodes" license = { file = "LICENSE" } requires-python = ">=3.10" diff --git a/workflow_node.py b/workflow_node.py index 9a8a61f..492f8bc 100644 --- a/workflow_node.py +++ b/workflow_node.py @@ -21,6 +21,27 @@ from .workflow_utils import ( log = configure_logger("ComfyUI-Subworkflow") +class _UnboundedOutputTypes: + """Returns '*' for any slot index so validation never IndexErrors on dynamic outputs.""" + def __getitem__(self, idx): + return "*" + def __len__(self): + return 0 + def __iter__(self): + return iter(()) + + +class _UnboundedFalseSeq: + """Infinite False iterator so merge_result_data zips correctly for any output count.""" + def __getitem__(self, idx): + return False + def __len__(self): + return 0 + def __iter__(self): + while True: + yield False + + def _apply_primitive_overrides(data: dict, kwargs: dict) -> dict: """ For INT/FLOAT inputs where the outer slot is not connected and the override @@ -369,3 +390,13 @@ class SubworkflowModifierSourceFromURL(BaseSubworkflow): validate_workflow_nodes_installed(data) output_refs, graph = build_modifier_source_expansion(data, kwargs) return cls._finalize_execution(output_refs, graph, data, reload_each_execution) + + +_DYNAMIC_RETURN = _UnboundedOutputTypes() +for _cls in (Subworkflow, SubworkflowFromURL, SubworkflowModifierSource, SubworkflowModifierSourceFromURL): + # Pre-set so GET_SCHEMA() doesn't overwrite with the empty list that outputs=[] produces. + # Returning '*' for any slot index lets validation accept connections to any output slot. + _cls._RETURN_TYPES = _DYNAMIC_RETURN + _cls._RETURN_NAMES = [] + _cls._OUTPUT_IS_LIST = _UnboundedFalseSeq() + _cls._OUTPUT_TOOLTIPS = []