Editor Result Gate
The node that refuses to fake an editor result
- editor_target
- firered_image
- klein_image
- qwen21_image
- direct_image
- image
What it's for
Once your workflow can run three different instruction editors, something has to pick the decoded output of whichever one is live and send it to the upscaler. The obvious implementation is a fallback switch: pass the first non-empty image and carry on.
PortraitUtils deliberately doesn't do that. If the selected editor produced nothing - because you muted its group, because the branch errored, because you forgot to connect the decode - the gate raises an error. It will not substitute another editor, and it will not quietly hand the unedited source photo to the upscaler and let you find out when the "enhanced" output looks suspiciously identical to the input. That silent-fallback failure mode is one of the more annoying ways a pipeline lies to you, so a gate that stops is worth having.
How it works
Required: editor_target (the typed PORTRAIT_EDITOR_TARGET from Active Editor Target) and allow_direct, a boolean defaulting off. Optional inputs, one per editor path:
firered_imageklein_imageqwen21_imagedirect_image
All four are lazy. The node requests exactly one of them - the socket matching the active target - so a branch that's connected but not selected isn't evaluated. That's not just tidiness; it means an inactive editor's decode doesn't get dragged into the execution graph.
Output: a single image, and the documented wiring is straight from here to the upscaler. That keeps exactly one path from the edit stage into finishing, which is the property you want when three optional branches converge.
Active Editor Target ── editor_target ─> Editor Result Gate ── image ─> upscaler
FireRed decode ──────> firered_image ───┘
Klein decode ────────> klein_image ─────┘
Qwen 2.1 decode ─────> qwen21_image ────┘
prepared_image ──────> direct_image ────┘
The allow_direct rule
Direct / No Editor is an explicit opt-in, not a fallback. If the active target is Direct and allow_direct is false, the gate errors telling you to enable exactly one editor group in your muter, or to set allow_direct if you really meant to bypass editing. Turn it on for a deliberate no-editor run and - this is the part people get wrong - turn it back off when editing is mandatory. Leave it on permanently and you've rebuilt the silent-fallback behaviour this node exists to prevent.
Read this before you open your old workflow
The 2.0 release is deliberately breaking here. The old qwen_image socket is gone with no compatibility alias; it's replaced by firered_image. Qwen 2511 and Flux Kontext targets are retired; the current set is Qwen Image Edit 2.1, FireRed Image Edit 1.1 and Flux 2 Klein Base. A saved 1.x workflow will show the gate with sockets that no longer exist until you delete and recreate it. Swapping JSON node IDs doesn't migrate socket order, so rewire rather than patch.
Also: keep the gate outside your Fast Groups Muter's editor groups. If it lives inside a group, muting that group removes the gate too, and the whole point of it is to still be standing when you've muted everything else. The pack's own guidance is to give the editor groups a dedicated muter with the "always one" restriction, rather than applying that restriction to your main muter.
Where people get burned
"Gate selected Qwen but qwen21_image has no image" is the error you'll see most, and it's usually one of two things: the decode is connected from the wrong place, or the Qwen branch is bypassed while its beacon is still live. Connect the decoded output - not the editor's input image, and not a shared pre-editor switch, which is exactly what the error message warns about.
If instead you get "no editor is active," every beacon is muted and allow_direct is off. That's the gate doing its job, not a bug.
Install
ComfyUI Manager → search PortraitUtils (publisher heyburns, GPLv3), or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/heyburns/PortraitUtils
/path/to/ComfyUI/venv/bin/python -m pip install -r PortraitUtils/requirements.txt
Dependencies (numpy, Pillow, opencv-python-headless, tifffile) go into ComfyUI's Python environment - one OpenCV variant only - and you must restart the ComfyUI server afterwards. The editor models are separate installations; this pack ships no weights.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| editor_target | PORTRAIT_EDITOR_TARGET | — | |
| allow_direct | BOOLEAN | false | Enable only when a deliberate Direct / No Editor run is intended. |
| firered_imageopt | IMAGE | — | |
| klein_imageopt | IMAGE | — | |
| qwen21_imageopt | IMAGE | — | |
| direct_imageopt | IMAGE | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |