Comfy-Org / Comfy-Org/ComfyUI

Subgraph flatten queues wrong widget values (off-by-one) - 113 shipping templates carry the defect, some corrupt silently (fix included)

Open
#15,102 1 comment 2 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
133k
Forks
15.7k
Avg merge
1d 7h
Merged PRs (30d)
158

Description

## Expected Behavior

Queueing a workflow containing a subgraph produces the same prompt values the UI displays.

## Actual Behavior

If a subgraph definition's inner node has a widget-input still linked to the subgraph input boundary (legacy promoted-widget style: the input entry carries a `widget` key and its `link` id appears in `definitions.subgraphs[].inputs[].linkIds`), and that boundary input is dangling (no parent-side instance feeds it a link, instance `widgets_values` empty), then flattening (`graphToPrompt`) falls back to positional `widgets_values` mapping and does not account for the `control_after_generate` pseudo-widget. Every widget value after the missed slot shifts by one:

- `steps` receives the seed value: `Value N bigger than max of 10000: steps`
- `sampler_name` receives a number: `'1' is not in list`

The UI renders all widget values (seed, steps, cfg, sampler_name, …) correctly. Only the generated prompt is wrong. So the defect gets reported against whatever node fails validation instead of the serialization bug. This is the actual root cause behind #13627 (analysis posted there: https://github.com/Comfy-Org/ComfyUI/issues/13627#issuecomment-5014885724) and likely behind other "promoted widgets wrong after upgrade" reports (#13029, #13326, #13157). Filing standalone because that issue's title makes it look z-image-specific.

## Steps to Reproduce

On the current core pin (frontend 1.45.20), with an official template:

1. Load `utility_seedvr2_3b_int8_upscale_video.json` from Comfy-Org/workflow_templates `main`.
2. The subgraph's KSampler shows sensible values in the UI (euler / simple / denoise 1.0).
3. Queue, or run `(await app.graphToPrompt()).output["66:54"].inputs` in the console.
4. Validation fails on that KSampler: `sampler_name` = `1`, `scheduler` = `1`, `denoise` = `"euler"`. The values shifted one slot.

Some corruptions run silently: `image_boogu_image_0_1_edit.json` (shipping templates package 0.1.6) flattens `noise_seed=true`, which validates as INT and runs with seed 1 instead of 22. Wrong output, no error. `video_capybara_v0_1_video_edit.json` similarly runs with `batch_index=121`.

## Scope

The trigger is the serialized subgraph structure, not any node or model family. Subgraphs freshly created with Convert to Subgraph serialize these inputs with `link: null` and are fine. The defect affects definitions created or imported from older frontends.

This defective serialization ships in official templates at scale (static scan 2026-07-26): 175 of 581 templates on Comfy-Org/workflow_templates `main`, and 113 of 471 in the shipping `comfyui-workflow-templates-json` 0.1.6 package, including the first-run onboarding template (`01_get_started_text_to_image.json`). Carrying it does not always corrupt. Which templates corrupt depends on the frontend version. Confirmed by prompt-diff on 1.45.20: `utility_seedvr2_3b_int8_upscale_video.json`, `templates-6-key-frames.json`, `video_capybara_v0_1_video_edit.json`, `gsl_creator_2.json`, `image_boogu_image_0_1_edit.json` / `_int8`. On 1.46.15: `image_z_image.json` (seed lands in `steps`, node `76:69` - that instance is #13627). Full scan listings and per-node diffs available on request.

Static detection without queueing: flag any inner-node input that (1) has a `widget` key, (2) has `link` in a boundary input's `linkIds`, and (3) that boundary input is dangling on every instance. Boundary widgets actually fed by a parent link resolve fine and must not be flagged.

## Versions

Confirmed on frontend 1.45.20 (core 0.27.0 pin, 2026-07-26) and 1.46.15 (z-image case, 2026-07-19). On ComfyUI_frontend `main` (2026-07-26), `SubgraphNode._applyPromotedWidgetValues` (src/lib/litegraph/src/subgraph/SubgraphNode.ts) still consumes `widgets_values` positionally with no `control_after_generate` handling, so the bug remains reachable on current code.

## Suggested fixes (increasing scope)

a. Skip `control_after_generate` in the positional fallback of the flatten path.
b. Treat dangling boundary-linked widget-inputs as `link: null` at load time (de-promote), matching what freshly created subgraphs serialize. Verified locally via before/after `graphToPrompt` inspection: this fixes affected workflows without restructuring the subgraph.
c. Structural end state: named widget values per Comfy-Org/ComfyUI_frontend#10392. Update: that PR merged 2026-07-30 behind the disabled-by-default `Comfy.Workflow.NamedValuesRestore` setting. The positional fallback is still the default path, so (a) or (b) is still needed.

Separately from the code fix: re-export the affected official templates from a current frontend, confirmed-corrupting ones first, so new users stop hitting this out of the box.

Scanner/fixer scripts available on request (the fixer validates every candidate against `/object_info` schema and flags rather than fixes anything it can't prove value-preserving).

Contributor guide

Open the contributing guide

Research direction

Start at graphToPrompt and SubgraphNode._applyPromotedWidgetValues in src/lib/litegraph/src/subgraph/SubgraphNode.ts, then reproduce with utility_seedvr2_3b_int8_upscale_video.json. Compare the generated prompt inputs with the values shown in the UI, focusing on dangling boundary-linked widgets and control_after_generate. Done means affected subgraphs retain the correct widget order and no values shift during queueing.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.