Qwen Image Edit Workflows

Build Qwen Image Edit workflows covering model loading, conditioning, LoRAs, prompt patterns, and XY plot testing

How to install

How to install

  1. Setup differs for this server — follow the Installation part of the README below.
  2. Claude Code: claude mcp add <name> -- <command>.
  3. Claude Desktop / Cursor: add it under mcpServers in the MCP config file.
Claude Code — installs the whole folder, not just SKILL.md
npx degit artokun/comfyui-mcp/plugin/skills/qwen-image-edit#main ~/.claude/skills/qwen-image-edit

For one project only, change the path to .claude/skills/qwen-image-edit. This skill also uses Widgets.json — copying SKILL.md alone won't be enough. See the folder on GitHub.

This one runs on your machine and can reach your files. Read the README below before you connect it.

Not working?
  • Check which app you pasted it into — the steps above name the right one.
  • Some skills need the paid tier of Claude or ChatGPT.
Step-by-step guide with screenshots · Ask in the forum

Paste into Claude, ChatGPT or Cursor.

Show the full text376 lines
qwen-image-edit/SKILL.md376 lines18.2 KBpushed 21d agoRawView on GitHub

Qwen Image Edit Workflows

Overview

Qwen Image Edit uses a vision-language model (Qwen2.5-VL) to edit images based on natural language instructions. The model "sees" the source image through CLIP conditioning and generates an edited version.

Models

Required Components

Component Node Model Name Notes
UNET UNETLoader qwen_image_edit_2511_bf16.safetensors Official 2511 edit model (bf16)
CLIP CLIPLoader (type=qwen_image) qwen_2.5_vl_7b_fp8_scaled.safetensors Shared across all Qwen models
VAE VAELoader qwen_image_vae.safetensors Qwen-specific VAE

Alternative UNET Models

Model Path Focus
qwenImageEditRemix_v10 qwenImageEditRemix_v10.safetensors Community remix, general editing
qwenUltimateRealism_v11 Qwen/imageized/qwenUltimateRealism_v11.safetensors Product photography, hyper-realistic
copaxTimeless Qwen/realistic/copaxTimeless_qwenUltraRealistic.safetensors Ultra-realistic portraits
qwnImageEdit_v16Bf16 Qwen/abliterated/qwnImageEdit_v16Bf16.safetensors Abliterated (uncensored)

Conditioning Nodes

TextEncodeQwenImageEditPlusAdvance_lrzjason (Recommended)

From the qweneditutils custom node pack. The Advanced variant is preferred because it:

  • Outputs a LATENT directly (no need for separate EmptyLatentImage)
  • Has separate VL-resize and non-resize image slots for fine control
  • Supports target_size control for output resolution
  • Includes a pad/center/disabled crop method with pad_info output
Required Inputs:
  - clip: CLIP
  - prompt: STRING — natural language edit instruction

Optional Inputs:
  - vae: VAE — needed for image encoding and latent output
  - vl_resize_image1-3: IMAGE — images that get VL-resized (downscaled for vision encoder)
  - not_resize_image1-3: IMAGE — images kept at full resolution
  - target_size: [1024, 1344, 1536, 2048, 768, 512] (default 1024)
  - target_vl_size: [392, 384] (default 384)
  - upscale_method: [lanczos, bicubic, area]
  - crop_method: [pad, center, disabled]
  - instruction: STRING — system instruction template (has sensible default)

Outputs (10):
  [0] conditioning_with_full_ref: CONDITIONING — use as positive conditioning
  [1] latent: LATENT — auto-scaled latent, feed directly to KSampler
  [2] target_image1: IMAGE — processed target-size image
  [3] target_image2: IMAGE
  [4] target_image3: IMAGE
  [5] vl_resized_image1: IMAGE — VL-resized version
  [6] vl_resized_image2: IMAGE
  [7] vl_resized_image3: IMAGE
  [8] conditioning_with_first_ref: CONDITIONING — conditioning with only first ref
  [9] pad_info: ANY — padding info for later unpadding

Key advantage: Output [1] (latent) eliminates the need for a separate EmptyLatentImage or VAEEncode node. The Advanced node handles latent creation internally at the correct resolution.

Other Conditioning Variants

  • TextEncodeQwenImageEditPlus (Phr00t v2, built-in) is simpler: 4 image inputs, outputs only CONDITIONING. Requires separate EmptyLatentImage. Good for quick edits.
  • TextEncodeQwenImageEditPlus_lrzjason: 5 image inputs, resize toggles, but less control than Advance
  • TextEncodeQwenImageEditPlusPro_lrzjason: Per-image VL resize selection via vl_resize_indexs string, main_image_index control

Lightning LoRAs (Fast Generation)

4-Step Lightning (2511 Edit)

{
  "class_type": "LoraLoaderModelOnly",
  "inputs": {
    "model": ["<unet_node>", 0],
    "lora_name": "Qwen-Image-Edit-2511-Lightning-4steps-V1.0-bf16.safetensors",
    "strength_model": 1.0
  }
}

Settings: steps=4, cfg=1.0, sampler=euler, scheduler=simple, denoise=1.0

4-Step Lightning (General Qwen)

For non-edit models (txt2img, 2512):

  • Qwen-Image-Lightning-4steps-V1.0.safetensors (strength 1.0)

8-Step Lightning

  • Qwen-Image-Lightning-8steps-V1.0.safetensors, higher detail than 4-step

Sampler Settings

Preset Steps CFG Sampler Scheduler Denoise LoRA
Lightning 4-step (2511 edit) 4 1.0 euler simple 1.0 2511-Lightning-4steps
Lightning 8-step 8 1.0 euler simple 1.0 Lightning-8steps
Standard edit 40 4.0 euler simple 0.75 none
Quality edit 50 4.0 euler simple 0.5-0.8 none

The sub-1.0 denoise rows REQUIRE a VAEEncode latent. A denoise low enough to shorten the sampling schedule — which 0.5-0.8 certainly is — keeps part of the incoming latent, so that latent has to BE the source image. Wire latent_image from a VAEEncode of the source (or from a node that emits a source-derived latent, like TextEncodeQwenImageEditPlusAdvance_lrzjason output [1]). Pairing these rows with an EmptyLatentImage runs clean and returns a flat, near-uniform field — an empty latent has no source content to preserve. Feeding the reference through TextEncodeQwenImageEditPlus does not rescue it: that image rides on CONDITIONING, which steers denoising but never seeds the sampler's starting state.

Denoise for editing: Lower denoise = closer to source — provided the latent IS the source. 0.5-0.8 range for standard editing on a VAEEncode latent. Lightning uses 1.0 (model handles fidelity internally).

Resolutions

This table is for Qwen-Image TEXT-TO-IMAGE. Do not pick an edit graph's output size from it. An edit graph's geometry is decided by the SOURCE image, not by you — see "Resolution on an edit graph" below. Choosing 1104x1472 here for an edit was #2681.

Qwen-Image operates at ~1.6 megapixels natively:

Aspect Resolution Use Case
Square 1328x1328 General
Portrait 3:4 1104x1472 Portraits
Portrait 9:16 928x1664 Phone format
Landscape 4:3 1472x1104 Landscape scenes
Landscape 16:9 1664x928 Widescreen
Video-ready 832x480 For WAN 2.2 FLF pipeline

For video pipelines: Use 832x480 to match WAN 2.2's default resolution.

Resolution on an edit graph

TextEncodeQwenImageEdit and TextEncodeQwenImageEditPlus do not take a size. They scale every reference image to a hard-coded int(1024 * 1024) px — ~1.05 MP, at the source's own aspect ratio — VAE-encode it, and hand it to the model as a reference latent (comfy_extras/nodes_qwen.py).

The model then lays the reference tokens and the tokens it is generating on one shared, centred coordinate grid (comfy/ldm/qwen_image/model.py, process_img), so reference position (i, j) and output position (i, j) mean the same place only when the two grids are the same size. That is the whole reason the official templates run the one image through FluxKontextImageScale and then feed the sampler a VAEEncode of that scaled image — both branches then see the same pixels at the same ~1 MP scale and the same aspect. Every PREFERRED_KONTEXT_RESOLUTIONS entry is ~1.05 MP for the same reason.

It is agreement to within the encoder's round-to-8, not exact equality, and the difference is worth knowing precisely. FluxKontextImageScale snaps to a preferred pair; the encoder then renormalises that to its own 1,048,576 px budget. For 12 of the 18 preferred pairs the two land on the same latent grid. For the other 6 — 688x1504, 800x1328, 832x1248 and their landscape mirrors — the reference lands one latent row or column off: at 800x1328 the sampler's grid is 100x166 and the reference's is 99x165. ComfyUI's own bundled 2511 template does exactly this, so a sub-patch offset is evidently fine in practice. The failure this page is about is one of SCALE, not of rounding — an empty latent at 1104x1472 sits 1.24x away linearly, not one row.

So on an edit graph you do not choose a resolution — you inherit one:

  • Right: LoadImage -> FluxKontextImageScale -> (TextEncodeQwenImageEditPlus and VAEEncode) -> KSampler latent_image.
  • Wrong: an EmptyLatentImage at a size from the table above. Its dimensions are literals; the reference's are computed from the source when the graph runs. At 1104x1472 (1.63 MP) against a 1.05 MP reference the grids are 1.24x apart linearly, the model cannot copy detail across them, and it re-synthesises the subject instead — materials come back looking plastic/CGI and printed detail comes back as a generic shape (#2681). Nothing errors; the image just is not the edit you asked for.

create_workflow (action:"validate") now flags this pairing as edit_reference_empty_latent.

Prompt Patterns

Edit Instructions (Natural Language)

"Change the black cat into a cute girl with a black bodysuit and jeans"
"Make the sky a dramatic sunset with orange and purple clouds"
"Add a red sports car parked in front of the house"
"Remove the person on the left and fill with the background"

Multi-Angle LoRA (qwen-image-edit-2511-multiple-angles-lora)

Uses <sks> token with structured angle/distance prompts:

<sks> front view eye-level shot close-up
<sks> front-right quarter view low-angle shot medium shot
<sks> back view elevated shot wide shot

Template: <sks> {direction} view {angle} shot {distance}

Directions: front, front-right quarter, right side, back-right quarter, back, back-left quarter, left side, front-left quarter Angles: low-angle, eye-level, elevated, high-angle Distances: close-up, medium shot, wide shot

Negative Conditioning

Always use ConditioningZeroOut for negative conditioning with Qwen edit:

{
  "class_type": "ConditioningZeroOut",
  "inputs": { "conditioning": ["<positive_cond_node>", 0] }
}

Complete Workflow: Lightning Edit (Advanced Node)

Uses TextEncodeQwenImageEditPlusAdvance_lrzjason, which outputs the latent directly, so no EmptyLatentImage is needed.

{
  "1": { "class_type": "UNETLoader", "inputs": { "unet_name": "qwen_image_edit_2511_bf16.safetensors", "weight_dtype": "default" }},
  "2": { "class_type": "LoraLoaderModelOnly", "inputs": { "model": ["1", 0], "lora_name": "Qwen-Image-Edit-2511-Lightning-4steps-V1.0-bf16.safetensors", "strength_model": 1 }},
  "3": { "class_type": "CLIPLoader", "inputs": { "clip_name": "qwen_2.5_vl_7b_fp8_scaled.safetensors", "type": "qwen_image" }},
  "4": { "class_type": "VAELoader", "inputs": { "vae_name": "qwen_image_vae.safetensors" }},
  "5": { "class_type": "LoadImage", "inputs": { "image": "<source_image.png>" }},
  "6": { "class_type": "TextEncodeQwenImageEditPlusAdvance_lrzjason", "inputs": {
    "clip": ["3", 0], "prompt": "<edit instruction>", "vae": ["4", 0],
    "vl_resize_image1": ["5", 0],
    "target_size": 1024, "target_vl_size": 384,
    "upscale_method": "lanczos", "crop_method": "pad"
  }},
  "7": { "class_type": "ConditioningZeroOut", "inputs": { "conditioning": ["6", 0] }},
  "8": { "class_type": "KSampler", "inputs": {
    "model": ["2", 0],
    "positive": ["6", 0],
    "negative": ["7", 0],
    "latent_image": ["6", 1],
    "seed": 42, "steps": 4, "cfg": 1, "sampler_name": "euler", "scheduler": "simple", "denoise": 1
  }},
  "9": { "class_type": "VAEDecode", "inputs": { "samples": ["8", 0], "vae": ["4", 0] }},
  "10": { "class_type": "SaveImage", "inputs": { "images": ["9", 0], "filename_prefix": "qwen_edit" }}
}

Key connections:

  • "latent_image": ["6", 1]: KSampler gets its latent directly from the Advanced node's output [1]
  • "positive": ["6", 0]: conditioning_with_full_ref from output [0]
  • "vl_resize_image1": ["5", 0]: source image goes into VL-resize slot (downscaled for vision encoder)

Simpler Alternative (Phr00t v2)

If qweneditutils custom node is unavailable, use the built-in TextEncodeQwenImageEditPlus with a separate EmptyLatentImage:

{
  "6": { "class_type": "TextEncodeQwenImageEditPlus", "inputs": {
    "clip": ["3", 0], "prompt": "<edit instruction>", "vae": ["4", 0], "image1": ["5", 0]
  }},
  "8": { "class_type": "EmptyLatentImage", "inputs": { "width": 1024, "height": 1024, "batch_size": 1 }}
}

Replace node 6 and add node 8. KSampler latent_image connects to ["8", 0] instead of ["6", 1].

Do not leave that EmptyLatentImage wired to the sampler. It is shown above only because it is what the Plus encoder's own signature leaves you needing, and it fails in a different way on each side of denoise 1.0:

  • Below 1.0 it renders a flat, near-uniform field, always. The encoder emits CONDITIONING only, so the latent is genuinely empty, and a truncated sigma schedule exists to preserve an incoming latent that here has nothing in it (#2678).
  • At 1.0 it renders a plausible image that is not your source — unless its width and height happen to equal the geometry the encoder derived, which is ~1.05 MP at the source's aspect ratio. A 1024x1024 empty latent over an exactly-square source does line up, and is fine. 1104x1472 over that same source does not: the model aligns reference and output on one shared grid, cannot copy across grids that far apart, and re-synthesises instead (#2681). See "Resolution on an edit graph".

The second case is the trap, because it depends on a source you may not have looked at and it fails silently. A VAEEncode removes the coincidence — it cannot be the wrong size, because it is derived from the same pixels the encoder saw.

Feed latent_image from a VAEEncode of the same image you gave the encoder, scaled once up front so both branches see the same pixels at the same scale:

{
  "5b": { "class_type": "FluxKontextImageScale", "inputs": { "image": ["5", 0] }},
  "6":  { "class_type": "TextEncodeQwenImageEditPlus", "inputs": {
    "clip": ["3", 0], "prompt": "<edit instruction>", "vae": ["4", 0], "image1": ["5b", 0]
  }},
  "8":  { "class_type": "VAEEncode", "inputs": { "pixels": ["5b", 0], "vae": ["4", 0] }}
}

KSampler latent_image connects to ["8", 0]. Any denoise is then meaningful: 1.0 for a full edit, sub-1.0 to stay closer to the source.

Basic Variant (Official ComfyUI Example)

The official "Qwen 2511 Edit Simple" example uses newer built-in nodes for model patching and image scaling:

Additional nodes in the official pipeline:

  • ModelSamplingAuraFlow (shift=3.1): Flow matching shift applied to the UNET. Used instead of ModelSamplingSD3.
  • CFGNorm (strength=1): Normalizes CFG guidance for more stable generation. Applied after ModelSamplingAuraFlow.
  • FluxKontextImageScale: Auto-scales input images to the correct resolution for Qwen. No manual size parameters needed.
  • FluxKontextMultiReferenceLatentMethod (method=index_timestep_zero): Applied to both positive and negative conditioning. Handles multi-reference latent indexing.
  • VAEEncode: Encodes the scaled image to latent (instead of EmptyLatentImage).

Official pipeline flow:

UNETLoader → [LoraLoaderModelOnly] → ModelSamplingAuraFlow (shift=3.1) → CFGNorm (strength=1) → MODEL
CLIPLoader (qwen_image) → CLIP
VAELoader → VAE

LoadImage → FluxKontextImageScale → scaled_image
  ├─ TextEncodeQwenImageEditPlus (positive) → FluxKontextMultiReferenceLatentMethod → positive CONDITIONING
  ├─ TextEncodeQwenImageEditPlus (negative, empty) → FluxKontextMultiReferenceLatentMethod → negative CONDITIONING
  └─ VAEEncode → LATENT

KSampler → VAEDecode → SaveImage

Official sampler settings:

Variant Steps CFG Sampler Scheduler Denoise LoRA
Standard 40 4.0 euler simple 1.0 none
Lightning 4 1.0 euler simple 1.0 2511-Lightning-4steps

Note: The FluxKontextMultiReferenceLatentMethod and FluxKontextImageScale nodes may not be needed when using Comfy's official model files directly, but may be required with community-repackaged models.

XY Plot Technique (from Widgets.json)

For batch-testing multiple edit variations, use the Easy Nodes XY Plot system:

  1. Text Multiline nodes define parameter lists (e.g., directions, angles)
  2. Split String breaks them into indexed options
  3. easy textIndexSwitch selects one at a time
  4. easy promptReplace substitutes {X}, {Y}, {Z} placeholders in the base prompt
  5. easy XYPlotAdvanced + easy XYInputs: PromptSR drives the sweep
  6. easy pipeIn bundles model/clip/vae/latent into a pipeline

This produces a grid image showing all combinations, useful for finding the best angle/distance/style for a given subject.

VRAM Considerations

  • Qwen 2511 edit bf16: ~10GB VRAM
  • CLIP (fp8): ~7GB VRAM
  • VAE: ~200MB
  • Total: ~17-18GB, fits comfortably on 24GB GPUs
  • Always clear_vram before loading if switching from another model family

Tips

  1. Upload source images first with upload_image (action:"image") before building the workflow
  2. Match output resolution to the next pipeline step (e.g., 832x480 for WAN FLF) — but only on a generation graph. On an edit graph the size is the source's; resize the RESULT afterwards instead of sampling at the size you want
  3. Lightning LoRA + denoise 1.0 works well. The model handles structure preservation through conditioning
  4. Take an edit graph's latent_image from a VAEEncode of the source, not from an EmptyLatentImage — at sub-1.0 denoise the empty latent decodes to a flat, near-uniform field (#2678), and at denoise 1.0 it is right only if its literal size happens to equal the geometry the encoder derived from the source, which is exactly the coincidence a VAEEncode removes (#2681). Neither failure errors. create_workflow (action:"validate") flags both pairings (partial_denoise_empty_latent, edit_reference_empty_latent)
  5. The lrzjason Pro variant is best for multi-image compositions where you need fine control over which images get VL-resized
  6. Use get_workflow (action:"analyze") to understand any saved Qwen edit workflow before modifying or executing it. It returns a structured summary, not raw JSON. Only use get_workflow when you need the actual JSON for enqueue_workflow or create_workflow (action:"modify").

Sources

  • Official: none found.
  • Empirical: sampler values, wiring, and prompt notes from working graphs in packs/ and observed renders; not a vendor prompting guide.
1---
2name: qwen-image-edit
3description: Build Qwen Image Edit workflows covering model loading, conditioning, LoRAs, prompt patterns, and XY plot testing
4globs:
5 - "**/*.json"
6---
7 
8# Qwen Image Edit Workflows
9 
10## Overview
11 
12Qwen Image Edit uses a vision-language model (Qwen2.5-VL) to edit images based on natural language instructions. The model "sees" the source image through CLIP conditioning and generates an edited version.
13 
14## Models
15 
16### Required Components
17 
18| Component | Node | Model Name | Notes |
19|-----------|------|------------|-------|
20| **UNET** | `UNETLoader` | `qwen_image_edit_2511_bf16.safetensors` | Official 2511 edit model (bf16) |
21| **CLIP** | `CLIPLoader` (type=`qwen_image`) | `qwen_2.5_vl_7b_fp8_scaled.safetensors` | Shared across all Qwen models |
22| **VAE** | `VAELoader` | `qwen_image_vae.safetensors` | Qwen-specific VAE |
23 
24### Alternative UNET Models
25 
26| Model | Path | Focus |
27|-------|------|-------|
28| `qwenImageEditRemix_v10` | `qwenImageEditRemix_v10.safetensors` | Community remix, general editing |
29| `qwenUltimateRealism_v11` | `Qwen/imageized/qwenUltimateRealism_v11.safetensors` | Product photography, hyper-realistic |
30| `copaxTimeless` | `Qwen/realistic/copaxTimeless_qwenUltraRealistic.safetensors` | Ultra-realistic portraits |
31| `qwnImageEdit_v16Bf16` | `Qwen/abliterated/qwnImageEdit_v16Bf16.safetensors` | Abliterated (uncensored) |
32 
33## Conditioning Nodes
34 
35### TextEncodeQwenImageEditPlusAdvance_lrzjason (Recommended)
36 
37From the `qweneditutils` custom node pack. The **Advanced** variant is preferred because it:
38- Outputs a **LATENT directly** (no need for separate EmptyLatentImage)
39- Has separate **VL-resize** and **non-resize** image slots for fine control
40- Supports **target_size** control for output resolution
41- Includes a **pad/center/disabled crop** method with pad_info output
42 
43```
44Required Inputs:
45 - clip: CLIP
46 - prompt: STRING — natural language edit instruction
47 
48Optional Inputs:
49 - vae: VAE — needed for image encoding and latent output
50 - vl_resize_image1-3: IMAGE — images that get VL-resized (downscaled for vision encoder)
51 - not_resize_image1-3: IMAGE — images kept at full resolution
52 - target_size: [1024, 1344, 1536, 2048, 768, 512] (default 1024)
53 - target_vl_size: [392, 384] (default 384)
54 - upscale_method: [lanczos, bicubic, area]
55 - crop_method: [pad, center, disabled]
56 - instruction: STRING — system instruction template (has sensible default)
57 
58Outputs (10):
59 [0] conditioning_with_full_ref: CONDITIONING — use as positive conditioning
60 [1] latent: LATENT — auto-scaled latent, feed directly to KSampler
61 [2] target_image1: IMAGE — processed target-size image
62 [3] target_image2: IMAGE
63 [4] target_image3: IMAGE
64 [5] vl_resized_image1: IMAGE — VL-resized version
65 [6] vl_resized_image2: IMAGE
66 [7] vl_resized_image3: IMAGE
67 [8] conditioning_with_first_ref: CONDITIONING — conditioning with only first ref
68 [9] pad_info: ANY — padding info for later unpadding
69```
70 
71**Key advantage**: Output [1] (latent) eliminates the need for a separate `EmptyLatentImage` or `VAEEncode` node. The Advanced node handles latent creation internally at the correct resolution.
72 
73### Other Conditioning Variants
74 
75- **TextEncodeQwenImageEditPlus** (Phr00t v2, built-in) is simpler: 4 image inputs, outputs only CONDITIONING. Requires separate EmptyLatentImage. Good for quick edits.
76- **TextEncodeQwenImageEditPlus_lrzjason**: 5 image inputs, resize toggles, but less control than Advance
77- **TextEncodeQwenImageEditPlusPro_lrzjason**: Per-image VL resize selection via `vl_resize_indexs` string, `main_image_index` control
78 
79## Lightning LoRAs (Fast Generation)
80 
81### 4-Step Lightning (2511 Edit)
82 
83```json
84{
85 "class_type": "LoraLoaderModelOnly",
86 "inputs": {
87 "model": ["<unet_node>", 0],
88 "lora_name": "Qwen-Image-Edit-2511-Lightning-4steps-V1.0-bf16.safetensors",
89 "strength_model": 1.0
90 }
91}
92```
93 
94**Settings**: steps=4, cfg=1.0, sampler=euler, scheduler=simple, denoise=1.0
95 
96### 4-Step Lightning (General Qwen)
97 
98For non-edit models (txt2img, 2512):
99- `Qwen-Image-Lightning-4steps-V1.0.safetensors` (strength 1.0)
100 
101### 8-Step Lightning
102 
103- `Qwen-Image-Lightning-8steps-V1.0.safetensors`, higher detail than 4-step
104 
105## Sampler Settings
106 
107| Preset | Steps | CFG | Sampler | Scheduler | Denoise | LoRA |
108|--------|-------|-----|---------|-----------|---------|------|
109| Lightning 4-step (2511 edit) | 4 | 1.0 | euler | simple | 1.0 | 2511-Lightning-4steps |
110| Lightning 8-step | 8 | 1.0 | euler | simple | 1.0 | Lightning-8steps |
111| Standard edit | 40 | 4.0 | euler | simple | 0.75 | none |
112| Quality edit | 50 | 4.0 | euler | simple | 0.5-0.8 | none |
113 
114> **The sub-1.0 denoise rows REQUIRE a `VAEEncode` latent.** A denoise low enough to
115> shorten the sampling schedule — which 0.5-0.8 certainly is — keeps part of the
116> incoming latent, so that latent has to BE the source image. Wire `latent_image` from
117> a `VAEEncode` of the source (or from a node that emits a source-derived latent, like
118> `TextEncodeQwenImageEditPlusAdvance_lrzjason` output [1]). Pairing these rows with an
119> `EmptyLatentImage` runs clean and returns a flat, near-uniform field — an empty latent
120> has no source content to preserve. Feeding the reference through
121> `TextEncodeQwenImageEditPlus` does **not** rescue it: that image rides on CONDITIONING,
122> which steers denoising but never seeds the sampler's starting state.
123 
124**Denoise for editing**: Lower denoise = closer to source — *provided the latent IS the source*. 0.5-0.8 range for standard editing on a `VAEEncode` latent. Lightning uses 1.0 (model handles fidelity internally).
125 
126## Resolutions
127 
128> **This table is for Qwen-Image TEXT-TO-IMAGE. Do not pick an edit graph's output
129> size from it.** An edit graph's geometry is decided by the SOURCE image, not by you
130> — see "Resolution on an edit graph" below. Choosing 1104x1472 here for an edit was
131> #2681.
132 
133Qwen-Image operates at ~1.6 megapixels natively:
134 
135| Aspect | Resolution | Use Case |
136|--------|-----------|----------|
137| Square | 1328x1328 | General |
138| Portrait 3:4 | 1104x1472 | Portraits |
139| Portrait 9:16 | 928x1664 | Phone format |
140| Landscape 4:3 | 1472x1104 | Landscape scenes |
141| Landscape 16:9 | 1664x928 | Widescreen |
142| Video-ready | 832x480 | For WAN 2.2 FLF pipeline |
143 
144**For video pipelines**: Use 832x480 to match WAN 2.2's default resolution.
145 
146### Resolution on an edit graph
147 
148`TextEncodeQwenImageEdit` and `TextEncodeQwenImageEditPlus` do not take a size. They
149scale every reference image to a hard-coded `int(1024 * 1024)` px — **~1.05 MP, at the
150source's own aspect ratio** — VAE-encode it, and hand it to the model as a reference
151latent (`comfy_extras/nodes_qwen.py`).
152 
153The model then lays the reference tokens and the tokens it is generating on **one
154shared, centred coordinate grid** (`comfy/ldm/qwen_image/model.py`, `process_img`), so
155reference position (i, j) and output position (i, j) mean the same place only when the
156two grids are the same size. That is the whole reason the official templates run the one
157image through `FluxKontextImageScale` and then feed the sampler a `VAEEncode` of *that*
158scaled image — both branches then see the same pixels at the same ~1 MP scale and the
159same aspect. Every `PREFERRED_KONTEXT_RESOLUTIONS` entry is ~1.05 MP for the same reason.
160 
161It is agreement to within the encoder's round-to-8, not exact equality, and the
162difference is worth knowing precisely. `FluxKontextImageScale` snaps to a preferred pair;
163the encoder then renormalises *that* to its own 1,048,576 px budget. For 12 of the 18
164preferred pairs the two land on the same latent grid. For the other 6 — 688x1504,
165800x1328, 832x1248 and their landscape mirrors — the reference lands one latent row or
166column off: at 800x1328 the sampler's grid is 100x166 and the reference's is 99x165.
167ComfyUI's own bundled 2511 template does exactly this, so a sub-patch offset is evidently
168fine in practice. **The failure this page is about is one of SCALE, not of rounding** — an
169empty latent at 1104x1472 sits 1.24x away linearly, not one row.
170 
171So on an edit graph you do not choose a resolution — you inherit one:
172 
173- **Right:** `LoadImage` -> `FluxKontextImageScale` -> (`TextEncodeQwenImageEditPlus`
174 *and* `VAEEncode`) -> KSampler `latent_image`.
175- **Wrong:** an `EmptyLatentImage` at a size from the table above. Its dimensions are
176 literals; the reference's are computed from the source when the graph runs. At
177 1104x1472 (1.63 MP) against a 1.05 MP reference the grids are 1.24x apart linearly,
178 the model cannot copy detail across them, and it re-synthesises the subject instead —
179 materials come back looking plastic/CGI and printed detail comes back as a generic
180 shape (#2681). Nothing errors; the image just is not the edit you asked for.
181 
182`create_workflow (action:"validate")` now flags this pairing as
183`edit_reference_empty_latent`.
184 
185## Prompt Patterns
186 
187### Edit Instructions (Natural Language)
188 
189```
190"Change the black cat into a cute girl with a black bodysuit and jeans"
191"Make the sky a dramatic sunset with orange and purple clouds"
192"Add a red sports car parked in front of the house"
193"Remove the person on the left and fill with the background"
194```
195 
196### Multi-Angle LoRA (qwen-image-edit-2511-multiple-angles-lora)
197 
198Uses `<sks>` token with structured angle/distance prompts:
199 
200```
201<sks> front view eye-level shot close-up
202<sks> front-right quarter view low-angle shot medium shot
203<sks> back view elevated shot wide shot
204```
205 
206**Template**: `<sks> {direction} view {angle} shot {distance}`
207 
208Directions: front, front-right quarter, right side, back-right quarter, back, back-left quarter, left side, front-left quarter
209Angles: low-angle, eye-level, elevated, high-angle
210Distances: close-up, medium shot, wide shot
211 
212## Negative Conditioning
213 
214Always use `ConditioningZeroOut` for negative conditioning with Qwen edit:
215 
216```json
217{
218 "class_type": "ConditioningZeroOut",
219 "inputs": { "conditioning": ["<positive_cond_node>", 0] }
220}
221```
222 
223## Complete Workflow: Lightning Edit (Advanced Node)
224 
225Uses `TextEncodeQwenImageEditPlusAdvance_lrzjason`, which outputs the latent directly, so no EmptyLatentImage is needed.
226 
227```json
228{
229 "1": { "class_type": "UNETLoader", "inputs": { "unet_name": "qwen_image_edit_2511_bf16.safetensors", "weight_dtype": "default" }},
230 "2": { "class_type": "LoraLoaderModelOnly", "inputs": { "model": ["1", 0], "lora_name": "Qwen-Image-Edit-2511-Lightning-4steps-V1.0-bf16.safetensors", "strength_model": 1 }},
231 "3": { "class_type": "CLIPLoader", "inputs": { "clip_name": "qwen_2.5_vl_7b_fp8_scaled.safetensors", "type": "qwen_image" }},
232 "4": { "class_type": "VAELoader", "inputs": { "vae_name": "qwen_image_vae.safetensors" }},
233 "5": { "class_type": "LoadImage", "inputs": { "image": "<source_image.png>" }},
234 "6": { "class_type": "TextEncodeQwenImageEditPlusAdvance_lrzjason", "inputs": {
235 "clip": ["3", 0], "prompt": "<edit instruction>", "vae": ["4", 0],
236 "vl_resize_image1": ["5", 0],
237 "target_size": 1024, "target_vl_size": 384,
238 "upscale_method": "lanczos", "crop_method": "pad"
239 }},
240 "7": { "class_type": "ConditioningZeroOut", "inputs": { "conditioning": ["6", 0] }},
241 "8": { "class_type": "KSampler", "inputs": {
242 "model": ["2", 0],
243 "positive": ["6", 0],
244 "negative": ["7", 0],
245 "latent_image": ["6", 1],
246 "seed": 42, "steps": 4, "cfg": 1, "sampler_name": "euler", "scheduler": "simple", "denoise": 1
247 }},
248 "9": { "class_type": "VAEDecode", "inputs": { "samples": ["8", 0], "vae": ["4", 0] }},
249 "10": { "class_type": "SaveImage", "inputs": { "images": ["9", 0], "filename_prefix": "qwen_edit" }}
250}
251```
252 
253**Key connections**:
254- `"latent_image": ["6", 1]`: KSampler gets its latent directly from the Advanced node's output [1]
255- `"positive": ["6", 0]`: conditioning_with_full_ref from output [0]
256- `"vl_resize_image1": ["5", 0]`: source image goes into VL-resize slot (downscaled for vision encoder)
257 
258### Simpler Alternative (Phr00t v2)
259 
260If `qweneditutils` custom node is unavailable, use the built-in `TextEncodeQwenImageEditPlus` with a separate `EmptyLatentImage`:
261 
262```json
263{
264 "6": { "class_type": "TextEncodeQwenImageEditPlus", "inputs": {
265 "clip": ["3", 0], "prompt": "<edit instruction>", "vae": ["4", 0], "image1": ["5", 0]
266 }},
267 "8": { "class_type": "EmptyLatentImage", "inputs": { "width": 1024, "height": 1024, "batch_size": 1 }}
268}
269```
270 
271Replace node 6 and add node 8. KSampler latent_image connects to `["8", 0]` instead of `["6", 1]`.
272 
273**Do not leave that `EmptyLatentImage` wired to the sampler.** It is shown above only
274because it is what the Plus encoder's own signature leaves you needing, and it fails in a
275different way on each side of denoise 1.0:
276 
277- Below 1.0 it renders a flat, near-uniform field, always. The encoder emits CONDITIONING
278 only, so the latent is genuinely empty, and a truncated sigma schedule exists to
279 preserve an incoming latent that here has nothing in it (#2678).
280- At 1.0 it renders a plausible image that is not your source — *unless* its width and
281 height happen to equal the geometry the encoder derived, which is ~1.05 MP at the
282 source's aspect ratio. A 1024x1024 empty latent over an exactly-square source does line
283 up, and is fine. 1104x1472 over that same source does not: the model aligns reference
284 and output on one shared grid, cannot copy across grids that far apart, and
285 re-synthesises instead (#2681). See "Resolution on an edit graph".
286 
287The second case is the trap, because it depends on a source you may not have looked at
288and it fails silently. A `VAEEncode` removes the coincidence — it cannot be the wrong
289size, because it is derived from the same pixels the encoder saw.
290 
291Feed `latent_image` from a `VAEEncode` of the same image you gave the encoder, scaled
292once up front so both branches see the same pixels at the same scale:
293 
294```json
295{
296 "5b": { "class_type": "FluxKontextImageScale", "inputs": { "image": ["5", 0] }},
297 "6": { "class_type": "TextEncodeQwenImageEditPlus", "inputs": {
298 "clip": ["3", 0], "prompt": "<edit instruction>", "vae": ["4", 0], "image1": ["5b", 0]
299 }},
300 "8": { "class_type": "VAEEncode", "inputs": { "pixels": ["5b", 0], "vae": ["4", 0] }}
301}
302```
303 
304KSampler `latent_image` connects to `["8", 0]`. Any denoise is then meaningful: 1.0 for
305a full edit, sub-1.0 to stay closer to the source.
306 
307### Basic Variant (Official ComfyUI Example)
308 
309The official "Qwen 2511 Edit Simple" example uses newer built-in nodes for model patching and image scaling:
310 
311**Additional nodes in the official pipeline:**
312 
313- **`ModelSamplingAuraFlow`** (shift=3.1): Flow matching shift applied to the UNET. Used instead of `ModelSamplingSD3`.
314- **`CFGNorm`** (strength=1): Normalizes CFG guidance for more stable generation. Applied after `ModelSamplingAuraFlow`.
315- **`FluxKontextImageScale`**: Auto-scales input images to the correct resolution for Qwen. No manual size parameters needed.
316- **`FluxKontextMultiReferenceLatentMethod`** (method=`index_timestep_zero`): Applied to both positive and negative conditioning. Handles multi-reference latent indexing.
317- **`VAEEncode`**: Encodes the scaled image to latent (instead of `EmptyLatentImage`).
318 
319**Official pipeline flow:**
320```
321UNETLoader → [LoraLoaderModelOnly] → ModelSamplingAuraFlow (shift=3.1) → CFGNorm (strength=1) → MODEL
322CLIPLoader (qwen_image) → CLIP
323VAELoader → VAE
324 
325LoadImage → FluxKontextImageScale → scaled_image
326 ├─ TextEncodeQwenImageEditPlus (positive) → FluxKontextMultiReferenceLatentMethod → positive CONDITIONING
327 ├─ TextEncodeQwenImageEditPlus (negative, empty) → FluxKontextMultiReferenceLatentMethod → negative CONDITIONING
328 └─ VAEEncode → LATENT
329 
330KSampler → VAEDecode → SaveImage
331```
332 
333**Official sampler settings:**
334 
335| Variant | Steps | CFG | Sampler | Scheduler | Denoise | LoRA |
336|---------|-------|-----|---------|-----------|---------|------|
337| Standard | 40 | 4.0 | euler | simple | 1.0 | none |
338| Lightning | 4 | 1.0 | euler | simple | 1.0 | 2511-Lightning-4steps |
339 
340**Note**: The `FluxKontextMultiReferenceLatentMethod` and `FluxKontextImageScale` nodes may not be needed when using Comfy's official model files directly, but may be required with community-repackaged models.
341 
342## XY Plot Technique (from Widgets.json)
343 
344For batch-testing multiple edit variations, use the Easy Nodes XY Plot system:
345 
3461. **Text Multiline** nodes define parameter lists (e.g., directions, angles)
3472. **Split String** breaks them into indexed options
3483. **easy textIndexSwitch** selects one at a time
3494. **easy promptReplace** substitutes `{X}`, `{Y}`, `{Z}` placeholders in the base prompt
3505. **easy XYPlotAdvanced** + **easy XYInputs: PromptSR** drives the sweep
3516. **easy pipeIn** bundles model/clip/vae/latent into a pipeline
352 
353This produces a grid image showing all combinations, useful for finding the best angle/distance/style for a given subject.
354 
355## VRAM Considerations
356 
357- Qwen 2511 edit bf16: ~10GB VRAM
358- CLIP (fp8): ~7GB VRAM
359- VAE: ~200MB
360- Total: ~17-18GB, fits comfortably on 24GB GPUs
361- **Always `clear_vram` before loading** if switching from another model family
362 
363## Tips
364 
3651. **Upload source images first** with `upload_image (action:"image")` before building the workflow
3662. **Match output resolution** to the next pipeline step (e.g., 832x480 for WAN FLF) — but only on a *generation* graph. On an edit graph the size is the source's; resize the RESULT afterwards instead of sampling at the size you want
3673. **Lightning LoRA + denoise 1.0** works well. The model handles structure preservation through conditioning
3684. **Take an edit graph's `latent_image` from a `VAEEncode` of the source, not from an `EmptyLatentImage`** — at sub-1.0 denoise the empty latent decodes to a flat, near-uniform field (#2678), and at denoise 1.0 it is right only if its literal size happens to equal the geometry the encoder derived from the source, which is exactly the coincidence a `VAEEncode` removes (#2681). Neither failure errors. `create_workflow (action:"validate")` flags both pairings (`partial_denoise_empty_latent`, `edit_reference_empty_latent`)
3695. The **lrzjason Pro variant** is best for multi-image compositions where you need fine control over which images get VL-resized
3706. **Use `get_workflow (action:"analyze")`** to understand any saved Qwen edit workflow before modifying or executing it. It returns a structured summary, not raw JSON. Only use `get_workflow` when you need the actual JSON for `enqueue_workflow` or `create_workflow (action:"modify")`.
371 
372## Sources
373 
374- **Official:** none found.
375- **Empirical:** sampler values, wiring, and prompt notes from working graphs in `packs/` and observed renders; not a vendor prompting guide.
376 

Discussion

From GitHub

4 comments on 1 thread

Claimed 2026-09-03T05:48:00Z — dispatched to a fix agent. Root cause confirmed against the **canonical** ComfyUI-Manager `extension-node-map.json` (5,614 packs / 40,656 exactly-owned class names), no reporter box needed. The resolver in `src/services/workflow-deps.ts` trusts a Manager `nodename_pattern` as if it were ownership. Measured on the real catalogue: | pattern | claimed by | class names it steals from OTHER packs | |---|---|---| | `Hunyuan` | `exedesign/Hunyuan…` | **182** | | `PulidFlux` | `PaoloC68/…` | 13 | | `Inspire$` | `ComfyUI Connection Helper` | **101** | | `Inspire$` | `Inspread the rest

**Status: fix complete, merge HELD on review capacity — not merged.** Two PRs exist for this issue (two agents collided): **#2777** (mine, gate-reviewed) and **#2775** (an independent fix by a sibling agent). Neither is merged. The codex review gate exhausted its account quota on round 6 (`exit 2 — INDETERMINATE`). An indeterminate gate is not a pass, so I am not merging on my own testing. **Root cause**, measured against the canonical ComfyUI-Manager catalogue (5,614 packs / 40,656 exactly-owned class names) rather than inferred — a `nodename_pattern` was being read as an ownership record. Itread the rest

Root cause confirmed on disk, from the catalogue everyone has rather than the reporter's box. `DemonGatanjieu/Anomalous_Model_Browser` — the repository this issue says was named as the owner of `Power Lora Loader (rgthree)` and the other three — publishes **`nodename_pattern: ".*"`**. In this machine's live `extension-node-map.json` (4,884 packs, 36,174 exactly-owned class names, 39 patterns) that single pattern matches **all 36,174** known class names, and the pack exactly owns **zero** of them. So any class the catalogue does not name exactly was attributable to that repo, and `install_deps`read the rest

Alternatives

Also in Illustration & art