From 8ce68e7d74a296602fa59cf82ab42cf804cb8c11 Mon Sep 17 00:00:00 2001 From: digital-garbage <133010426+digital-garbage@users.noreply.github.com> Date: Sun, 7 Jun 2026 13:08:00 +0300 Subject: [PATCH] Movie Editor: fix forceInput-STRING blocking generation; surface exact blocker; move core panel up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Regression fix: making forceInput STRING sockets count as connection inputs made auto-wire treat them as required inputs needing a STRING source — with none, the builder blocked with 'no source available' while the Requirements panel (model/clip/ vae/latent/image only) stayed green. forceInput widget sockets always have a widget fallback, so connection_inputs now marks them required=False: still wireable, never blocking. Resolves 'A required pipeline input has no source' with everything green. - Generation errors now pass through the builder's 'Generation blocked — . (): …' detail instead of a vague generic message, so the exact culprit shows. - Built-in pipeline panel moved directly under Pipeline requirements so it's findable. Co-Authored-By: Claude Opus 4.8 --- movie_editor/backend/nodes.py | 12 ++++++++---- movie_editor/frontend/models.js | 2 +- movie_editor/frontend/store.js | 4 +++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/movie_editor/backend/nodes.py b/movie_editor/backend/nodes.py index 7c68cf0c..4b66ebc0 100644 --- a/movie_editor/backend/nodes.py +++ b/movie_editor/backend/nodes.py @@ -116,10 +116,14 @@ def connection_inputs(node_def: dict) -> list[dict]: if not isinstance(t, str): continue opts = spec[1] if len(spec) > 1 and isinstance(spec[1], dict) else {} - # A widget-typed input is a SOCKET (wireable) only when forceInput is set — - # e.g. refinement_key_input is ("STRING", {"forceInput": True}). Plain widgets - # are handled by widget_inputs, not here. - if t in _WIDGET_TYPES and not opts.get("forceInput"): + if t in _WIDGET_TYPES: + # A widget-typed input is a SOCKET (wireable) only when forceInput is set — + # e.g. refinement_key_input is ("STRING", {"forceInput": True}). It always + # has a widget fallback, so it's NEVER auto-required (it must not block + # generation when left unwired). Plain widgets are handled by widget_inputs. + if not opts.get("forceInput"): + continue + out.append({"name": name, "type": _normalize_type(t), "required": False}) continue # V3 nodes can mark a required-group input as optional via the flag. is_required = group == "required" and not opts.get("optional", False) diff --git a/movie_editor/frontend/models.js b/movie_editor/frontend/models.js index 825293d0..95082092 100644 --- a/movie_editor/frontend/models.js +++ b/movie_editor/frontend/models.js @@ -735,9 +735,9 @@ function body() { const b = el("div", "models-body"); b.append(requirementsPanel()); + b.append(coreSection()); b.append(composer()); b.append(linksSection()); - b.append(coreSection()); const v = validation(); const list = el("div", "slot-list"); if (!config.slots.length) list.append(el("div", "empty-stage", "No models configured yet — use the form above to add loaders.")); diff --git a/movie_editor/frontend/store.js b/movie_editor/frontend/store.js index 7ee52d16..e0f0710c 100644 --- a/movie_editor/frontend/store.js +++ b/movie_editor/frontend/store.js @@ -294,12 +294,14 @@ [/\.vae.*no source/i, "Missing Video VAE — add a Video VAE loader in Models."], [/\.model.*no source/i, "Missing diffusion model — add a Unet loader in Models."], [/\.clip.*no source/i, "Missing text encoder — add a CLIP loader in Models."], - [/no source available/i, "A required pipeline input has no source — open Models and check the Pipeline requirements checklist."], [/not installed/i, "A configured node class is not installed in ComfyUI — check Models for details."], [/Node registry unavailable/i, "ComfyUI is offline or still starting up — wait a moment and try again."], ]; function _friendlyGenError(raw) { + // "Generation blocked — …" already names the exact input(s); pass it through so the + // message is actionable instead of a vague "a required input has no source". + if (/Generation blocked/i.test(raw)) return raw; for (const [pat, msg] of GEN_ERROR_MAP) if (pat.test(raw)) return msg; return raw; }