Inpaint Composite
The node that guarantees your untouched pixels are untouched
- generated
- context
- image
Why a composite node is not optional
There's a post from late 2024 that still gets linked: "This looks like an epidemic of bad workflows practices. PLEASE composite your image after inpainting!" The complaint was that a wave of published workflows ran the whole frame through an inpaint sampler, decoded it, and called it done - so every pass nudged every pixel, and three or four passes turned a good image to mush.
The rule that came out of that: don't let the VAE decode/encode cycle touch pixels that weren't masked. Inpaint Composite is the enforcement of that rule as a node. It takes the generated sampling canvas and pastes it into the original using the effective mask, at source resolution, and pixels outside the mask come back unchanged - not blended with an alpha of zero and hoping, actually copied.
How it works
It needs two inputs and that's it:
generated- "Generated sampling canvas." The decode of whatever your sampler produced, at the canvas size Inpaint Prepare gave you.context- "Context from Adachi Inpaint Prepare." TheADACHI_INPAINT_CONTEXTwire.- Output:
image, one image per generated image, back at the original's size.
The context is the clever part, and it's why this node can't be swapped for a generic ImageCompositeMasked. That object carries the original pixels, the effective mask (after blur, grow, invert and soft edge), the crop box, the content rectangle inside the padded canvas, the canvas size, the fill mode, and an empty-flag. So the composite doesn't have to guess anything: it crops the generated canvas down to the content rect, bicubically resizes that patch to exactly the crop box's dimensions, and writes it in.
The paste itself is one line of torch.where(alpha > 0, source * (1 - alpha) + patch * alpha, source). That comparison is the whole guarantee. Where the mask is zero, the original branch of the select is used, so the value is bit-identical to what came in. Where the mask is partially feathered, you get a real blend. That's what makes mask blur safe: a soft edge means a soft transition, not a soft everything else.
Batch handling is also explicit. If your generated batch is a whole multiple of the original batch, image i maps to original i // repetitions - so four variants of image A land back on A. If the generated batch isn't a multiple, you get a clear error rather than a silently mismatched paste.
Where it sits in the graph
This is the last node of the modular pipeline, the one you use when you don't want the pack's all-in-one sampler:
Inline Mask.image → Inpaint Prepare.image
Inline Mask.mask → Inpaint Prepare.mask
Inpaint Prepare.pixels → VAE Encode
Inpaint Prepare.mask → Set Latent Noise Mask.mask
VAE Encode → Set Latent Noise Mask → KSampler → VAE Decode → Inpaint Composite.generated
Inpaint Prepare.context → Inpaint Composite.context
That's the shape from the pack's examples/02-modular-inpaint.json, and the README bolds one instruction: always connect Prepare.context to Composite.context. Not a reroute, not a second Prepare's context from a nearby branch - the one that made the canvas you sampled. Feeding it a context from elsewhere raises an explicit "Connect the context output from Adachi Inpaint Prepare" style error, which is the good failure mode.
What that buys you over rolling your own crop-and-paste: the effective mask is computed once, so what you blurred is what gets composited (not what you painted), and the crop geometry - padding, aspect expansion, replicate-pad regions - is remembered instead of reconstructed from four loose integers.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/adachi0130/Adachi-Inpaint-Workbench.git
Restart ComfyUI fully, hard-refresh the browser. Nothing to download, no extra dependencies beyond the numpy / Pillow / torch that ComfyUI already runs on. If you only want Prepare and Composite you still install the whole pack - the nodes are shipped together and the pack is MIT licensed, so there's no reason to cherry-pick.
Common issues
Everything came back at the wrong size. It didn't - the output is always the source image's size. width and height on Prepare describe the sampling canvas, not the output. If you want a different final size, resize after the composite.
A variant list got shuffled across images. Group variants per source (A,A,B,B), don't interleave them (A,B,A,B). The composite maps by position, and interleaving breaks that mapping in a way it can't detect.
A hard rectangle instead of a seam-free patch. Look upstream, not here. mask_blur on Prepare handles the edge, and padding gives the sampler surrounding context to match colour and texture against. The composite faithfully pastes whatever you handed it.
It's also the same design decision that made crop-and-stitch the default inpainting pattern of 2026: keep the mask, keep the guarantee, run the model on a crop instead of your whole image. Adachi just splits it into a prepare half and a paste half so you can put any sampler in the middle.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| generated | IMAGE | Generated sampling canvas. | |
| context | ADACHI_INPAINT_CONTEXT | Context from Adachi Inpaint Prepare. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |