Skip to content

Drop the duplicate first image from the Qwen-Image-Layered blueprint - #15364

Open
christian-byrne wants to merge 2 commits into
masterfrom
fix/qwen-layered-blueprint-drop-duplicate-first-image
Open

Drop the duplicate first image from the Qwen-Image-Layered blueprint#15364
christian-byrne wants to merge 2 commits into
masterfrom
fix/qwen-layered-blueprint-drop-duplicate-first-image

Conversation

@christian-byrne

Copy link
Copy Markdown
Contributor

The bug

EmptyQwenImageLayeredLatentImage allocates layers + 1 temporal slots:

# comfy_extras/nodes_qwen.py:129
latent = torch.zeros([batch_size, 16, layers + 1, height // 8, width // 8], device=...)

Slot 0 is the model's regenerated copy of the original image, not a layer.

The Image to Layers(Qwen-Image-Layered) blueprint feeds the sampler output straight into LatentCutToBatch(dim="t", slice_size=1), which reshapes the entire temporal axis into the batch dimension, and decodes all of it. Nothing drops the redundant frame, so asking for 2 layers returns 3 images with no indication that the first is a duplicate.

Confirmed by comfyanonymous:

yeah our qwen layered template is slightly wrong, the first image is exactly the same as the original and should be discarded

and all the layers when composited together should recreate the original image

The fix

Insert a LatentCut(dim="t", index=1, amount=16384) between KSampler and LatentCutToBatch:

KSampler -> LatentCut("t", 1, 16384) -> LatentCutToBatch("t", 1) -> VAEDecode

Before and after node chain

The figure above is rendered directly from the blueprint JSON — node positions, sizes, titles, slot types, widget values and link routing all come from the file (before = origin/master, after = this branch). It is deliberately not presented as a screenshot of a running ComfyUI: I do not have the Qwen-Image-Layered weights (~50 GB VRAM) and would not fake a UI capture.

LatentCut already exists (comfy_extras/nodes_latent.py:175-215, added in #9609) and predates LatentCutToBatch (#11411), which this blueprint already uses. No node changes.

Cutting in latent space rather than adding an ImageFromBatch after VAEDecode avoids a full-canvas VAE decode that would immediately be discarded. amount is MAX_RESOLUTION because LatentCut clamps it to what exists (nodes_latent.py:209), so it reads as "everything from index 1 onward" for any layers value, and layers = 0 still degrades correctly to the single original image — wiring the subgraph's layers input into amount instead would fail validation at layers = 0, since the widget's minimum is 1.

Effect

layers before after
0 1 image (the original) 1 image (unchanged)
1 2 images 1
2 (blueprint default) 3 images 2
3 4 images 3
8 9 images 8

Correct under batch_size > 1 as well: with layers=3, batch_size=2 the output goes from 8 images ([0,1,2,3,0,1,2,3]) to 6 ([1,2,3,1,2,3]).

What changed

One file: blueprints/Image to Layers(Qwen-Image-Layered).json — one new node, one new link, one re-targeted link, plus the lastNodeId / lastLinkId counters. No existing node moved or resized; the new node takes the next free order value so the subgraph keeps its contiguous unique order sequence.

This blueprint is duplicated across two repos, and nothing keeps them in sync

Worth stating plainly, because it is the reason this PR exists separately at all:

  • Nothing syncs Comfy-Org/ComfyUI and Comfy-Org/workflow_templates. No workflow, bot, script or CI check in either repo compares them. workflow_templates' scripts/blueprints/import_blueprints.py --source is a manual, opt-in copy from an arbitrary local directory and has no knowledge of this repo. Both copies are hand-committed by humans in ordinary feature PRs, which is the only reason they have stayed identical so far.
  • Neither is authoritative, and the pip package is not the bridge. This repo serves blueprints from its own git-tracked directory only — app/subgraph_manager.py:98 globs <ComfyUI>/blueprints/*.json, with no importlib.resources lookup, no folder_paths indirection and no fallback. And although requirements.txt:2 pins comfyui-workflow-templates==0.11.31, that meta package does not depend on comfyui-subgraph-blueprints, so pip install -r requirements.txt installs the blueprint manifest metadata but not a single blueprint JSON asset.
  • Net effect: this file is the only copy a running ComfyUI ever reads. Patching workflow_templates alone would not fix anything for users, and patching this alone would not fix the PyPI/cloud consumers. Both must land.

Filed as #15363 so the duplication is tracked independently of this bug.

Companion PR

Comfy-Org/workflow_templates carries an independent copy of this blueprint at blueprints/image_to_layers_qwen_image_layered.json (plus the generated mirror under packages/blueprints/), and the two shipped templates that have the same bug. Patched in Comfy-Org/workflow_templates#1092. Land both together or the copies drift.

Also outstanding over there: the template gallery thumbnails still show the duplicate and need re-shooting by someone with the weights.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ea6c5130-dc43-457b-a3a0-ff548b601a90

📥 Commits

Reviewing files that changed from the base of the PR and between cbbc9da and 84945ba.

📒 Files selected for processing (1)
  • blueprints/Image to Layers(Qwen-Image-Layered).json
📜 Recent review details
⏰ Context from checks skipped due to timeout. (14)
  • GitHub Check: Run Pylint
  • GitHub Check: test
  • GitHub Check: test (ubuntu-latest)
  • GitHub Check: test (macos-latest)
  • GitHub Check: test (windows-2022)
  • GitHub Check: test (macos-latest)
  • GitHub Check: test (windows-latest)
  • GitHub Check: test (ubuntu-latest)
  • GitHub Check: Build Test (3.10)
  • GitHub Check: Build Test (3.13)
  • GitHub Check: Build Test (3.11)
  • GitHub Check: Build Test (3.12)
  • GitHub Check: Build Test (3.14)
  • GitHub Check: Run Pylint
🧰 Additional context used
📓 Path-based instructions (4)
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Keep changes small, direct, and limited to the narrowest necessary code path and smallest number of files.
Prefer practical fixes, minimal dependencies, and existing repository patterns; remove obsolete, dead, unreachable, or unused code.
Preserve existing APIs, node names, model-loading behavior, file layout, and workflow compatibility unless replacement is explicitly intended.
Core ComfyUI must not add outbound internet requests, telemetry, tracking, reporting, remote configuration, or background network activity. User-authorized model downloads are limited to the requested artifact and must exclude telemetry and unrelated metadata.

Files:

  • blueprints/Image to Layers(Qwen-Image-Layered).json
**/*.{py,json}

📄 CodeRabbit inference engine (AGENTS.md)

Treat legacy combo, io.Combo, and io.DynamicCombo values affecting filesystem access as untrusted; revalidate them at load/save boundaries with folder_paths, containment checks, or fixed allowlists.

Files:

  • blueprints/Image to Layers(Qwen-Image-Layered).json
**/*.{py,md,txt,json}

📄 CodeRabbit inference engine (AGENTS.md)

Keep warning and info messages short and actionable, remove noisy or misleading logging, and make documentation edits concise, factual, and tied to changed behavior.

Files:

  • blueprints/Image to Layers(Qwen-Image-Layered).json
**

⚙️ CodeRabbit configuration file

**: IMPORTANT: Only comment on issues directly introduced by this PR's code changes.
Treat AGENTS.md as mandatory repository policy, not optional style guidance.
Flag PR changes that violate AGENTS.md even when the code is otherwise functional.
In particular, enforce architecture boundaries, dtype/device/memory rules,
interface contracts, import style, no unnecessary try/except blocks, no inline
imports, no outbound internet paths in core ComfyUI, and narrow scoped fixes.
Prefer direct findings over suggestions when a rule is violated. Only ignore
AGENTS.md when it clearly conflicts with a newer explicit maintainer instruction
in the PR.
Do NOT flag pre-existing issues in code that was merely moved, re-indented,
de-indented, or reformatted without logic changes. If code appears in the diff
only due to whitespace or structural reformatting (e.g., removing a with: block),
treat it as unchanged. Contributors should not feel obligated to address
pre-existing issues outside the scope of their contribution.

Files:

  • blueprints/Image to Layers(Qwen-Image-Layered).json
🧠 Learnings (1)
📚 Learning: 2026-05-10T17:25:49.999Z
Learnt from: comfyui-wiki
Repo: Comfy-Org/ComfyUI PR: 13570
File: blueprints/Remove Background (BiRefNet).json:233-237
Timestamp: 2026-05-10T17:25:49.999Z
Learning: In this ComfyUI blueprints repository, Hugging Face model URLs may intentionally use the mutable `/resolve/main/` form (e.g., `https://huggingface.co/<repo>/<model>/resolve/main/...`) instead of pinning to an immutable commit SHA. When reviewing blueprint JSON files, do not flag these URLs for lacking a revision/commit pin if they use `/resolve/main/` as shown.

Applied to files:

  • blueprints/Image to Layers(Qwen-Image-Layered).json
🔇 Additional comments (1)
blueprints/Image to Layers(Qwen-Image-Layered).json (1)

3-3: LGTM!

Also applies to: 167-168, 718-799, 819-819, 1519-1519, 1666-1673


📝 Walkthrough

Walkthrough

The blueprint adds a LatentCut node between KSampler and LatentCutToBatch. It configures the node to cut dimension t at index 1 with amount 16384. Existing link 142 now targets LatentCut, and new link 381 connects LatentCut to LatentCutToBatch. Node and link counters increase accordingly.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the main change: removing the duplicate first image from the Qwen-Image-Layered blueprint.
Description check ✅ Passed The description directly explains the bug, the latent-space fix, affected file, expected behavior, and companion change.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@christian-byrne

Copy link
Copy Markdown
Contributor Author

CI note: no GitHub Actions workflows have run on this PR yet. GitHub has had an Actions incident open since 2026-08-06 15:22 UTC — "Webhook triggers remain throttled to aid recovery, so many push and pull request events are not triggering new workflow runs." Other PRs opened in the same window show the same empty check list. I'll re-trigger and drive the checks to green once Actions recovers.

EmptyQwenImageLayeredLatentImage allocates layers + 1 temporal slots and slot 0
is the model's regenerated copy of the original image, not a layer. The
blueprint splits the whole temporal axis into a batch and decodes all of it, so
asking for 2 layers returns 3 images.

Insert LatentCut(dim=t, index=1, amount=16384) between KSampler and
LatentCutToBatch so the redundant slot is dropped in latent space rather than
VAE-decoded and shown.

Comfy-Org/workflow_templates carries an independent copy of this same blueprint;
it is patched identically in a companion PR.
@christian-byrne
christian-byrne force-pushed the fix/qwen-layered-blueprint-drop-duplicate-first-image branch from b486176 to c532115 Compare August 7, 2026 02:11
@alexisrolland

Copy link
Copy Markdown
Member

This lgtm, @comfyui-wiki I'd like to confirm with you it's ok to merge?

@comfyui-wiki

Copy link
Copy Markdown
Member

Already tested, LGTM @alexisrolland

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants