Superside Z-Image Skin-Detail Inpaint (fixed LoRA)
Z-Image Turbo Skin Inpainting When the Workflow JSON Can't Carry a LoRA URL
- image
- mask
- image
- info
Let's get the honest framing out of the way first: if you're running a normal ComfyUI install, you probably want the other node - Superside Z-Image Turbo Inpaint+LoRA - because this one is a special edition for a specific deployment constraint. This node runs the exact same Z-Image Turbo masked inpainting, but with both LoRA URLs hardcoded in the code instead of exposed as inputs. That sounds backwards until you meet the reason it exists.
Why the LoRA URLs are hidden
Some deployments - the README names cog-comfyui / Replicate - run a "weights preflight" scan over every string in the exported workflow JSON before executing. Any string that looks like a raw model-weight URL (.safetensors and friends) that isn't in a curated manifest gets rejected. Because lora_url and skin_detail_lora_url aren't declared as inputs on this node, they can never be serialized into the JSON, so the scan has nothing to catch. The trained skin-detail LoRA still gets applied - it's just baked into the node code rather than carried in the workflow.
If you're on a normal ComfyUI instance not subject to that scan, use the generic node where you can edit the LoRA URLs. This one exists to keep the same re-skin pipeline running in sandboxed, export-scanned environments.
How it works (the parts that matter either way)
It's masked image-to-image inpainting on Z-Image Turbo (the distilled few-step model from Tongyi-MAI), one fal call replacing what would be a local VAEEncode → SetLatentNoiseMask → LoRA loader → KSampler → VAEDecode chain. The inputs that actually do the work:
image+mask(white = regenerate) +prompt+api_key- the four required inputs.strength- the denoise, same role as a KSampler's. 0.4 default; 1.0 fully regenerates the masked area, 0.0 leaves it untouched. This is the dial for how aggressive the re-skin is.num_inference_steps- max 8, because Turbo is a distilled few-step model; 8 is its ceiling, don't look for more.match_input_resolution(default ON) - generate at the input's own resolution (rounded to a multiple of 16) instead of fal's small default presets. Leave it on for a cropped high-res face; the README notes the request is internally clamped to roughly a 2048px long-edge ceiling, so pair with a real upscaler afterward for more detail.lora_1_scale…lora_3_scale- strengths for the (hidden, fixed) LoRAs; default 1.0 each.control_scale(0.75) withcontrol_start/control_end- structural conditioning taken from the input image; this is what holds the face's shape while the skin re-renders.
Outputs: image (IMAGE) and info (STRING, result URL).
Installing it
Same as the whole pack - clone, install requirements, restart, paste your api_key:
cd ComfyUI/custom_nodes
git clone https://github.com/Superside/comfyui-superside-nodes.git
cd comfyui-superside-nodes
pip install -r requirements.txt
No model files - Z-Image runs on fal; every call is metered and your image leaves the machine.
The honest take
The fix applies to both this and the generic node (the README says bug fixes propagate), so it's not a stale fork - it's the same logic with a different input surface. Choose by deployment, not by vibes: normal ComfyUI → generic editable node; export-scanned sandbox → this one. And wherever you run it, remember the effective resolution ceiling and the few-step max; those two constraints shape every workflow you build around it.
Inputs (20)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| mask | MASK | — | |
| prompt | STRING | — | |
| api_key | STRING | — | |
| lora_1_scaleopt | FLOAT | 1.000–8 | Strength of lora_1_url. Ignored if lora_1_url is empty. |
| lora_2_scaleopt | FLOAT | 1.000–8 | Strength of lora_2_url. Ignored if lora_2_url is empty. |
| lora_3_scaleopt | FLOAT | 1.000–8 | Strength of lora_3_url. Ignored if lora_3_url is empty. |
| strengthopt | FLOAT | 0.400–1 | Inpaint strength - same role as a KSampler's denoise. 1.0 = fully regenerate the masked area, 0.0 = keep it untouched. |
| num_inference_stepsopt | INT | 81–8 | Z-Image Turbo is a distilled few-step model; 8 is its max. |
| seedopt | INT | -1-1–2147483647 | -1 = random |
| num_imagesopt | INT | 11–4 | — |
| image_sizeopt | COMBO | auto | "auto" keeps the input image's own size/aspect ratio. |
| control_scaleopt | FLOAT | 0.750–1 | Strength of the structural conditioning taken from the input image. |
| control_startopt | FLOAT | 0.000–1 | — |
| control_endopt | FLOAT | 0.800–1 | — |
| enable_prompt_expansionopt | BOOLEAN | false | — |
| enable_safety_checkeropt | BOOLEAN | true | — |
| output_formatopt | COMBO | png | 3 options: png, jpeg, webp |
| accelerationopt | COMBO | regular | 3 options: none, regular, high |
| match_input_resolutionopt | BOOLEAN | true | Generate at the input image's own resolution (rounded to a multiple of 16) instead of fal's image_size preset. fal's 'auto'/enum presets default to a small size (~512px short side) which looks flat/soft on a cropped high-res photo - enable this to keep full detail. Disable to use the image_size dropdown above instead. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| info | STRING | — |