Grow Mask
The padding your inpaints never knew they needed
- mask
- MASK
Grow Mask is the node you didn't know you were missing until your first inpainted fix came out looking like someone cut a hole and glued the patch in. It expands or shrinks a mask by a set number of pixels, and that one move fixes more mask problems than any other trick in ComfyUI. If you've ever wondered why your inpainting looks like a sticker, the answer is usually that you never gave the model any room to blend.
Why you'll reach for it
A mask in ComfyUI is a [B,H,W] float tensor where 1.0 means "regenerate here" and 0.0 means "leave this alone." The problem is that the region you paint is rarely the region the model needs. Inpainting wants context: the model blends best when there's a ring of original pixels around the fix, which is why every serious inpainting recipe grows the mask a little before it hits the sampler. A1111 calls this "inpaint at full resolution padding"; ComfyUI's VAE Encode (for inpainting) even has a grow_mask_by input, capped at 64 pixels. Grow Mask is the standalone version with no cap, so it works anywhere.
The other classic use is shrinking, and it's the fix for a specific, infuriating artifact: the white halo ring around a composited subject. IC-Light users learn this one fast - the standard advice is to "choke the mask by 1px and premultiply the alpha" before compositing. A negative expand does the choking.
How it works
For each pixel of expand, the node applies a 3x3 morphological operation - scipy's grey dilation if you're growing, grey erosion if you're shrinking. Repeated abs(expand) times. That last part matters more than you'd think, because it runs in plain Python on the CPU, one mask at a time. Grow by 200 pixels and you're doing 200 sequential passes over a numpy array. It's fine for a 512x512 mask, but keep an eye on it for big values on large masks - it's the slowest step in an otherwise-GPU pipeline, and there's nothing clever about it.
tapered_corners (on by default) changes the kernel from a full 3x3 square to a cross. A cross grows edges but leaves the diagonals to catch up, which keeps corners from turning into blocky steps. Turn it off if you want the corners to extend at the same rate as the edges - for most people the default is right, and the "tapered" look is usually what you actually wanted.
The inputs that matter
mask- what you're growing or shrinking.expand- pixels to add (positive) or remove (negative). This is the whole job. Zero is a no-op.tapered_corners- leave it on.
One output, MASK, which you feed straight into VAE Encode (for inpainting), a ControlNet inpaint condition, or a composite node.
Getting it
It ships with ComfyUI core, no install. It lives in comfy_extras/nodes_mask.py alongside the rest of the built-in mask family, and it's been there since the early days - this is one of the oldest nodes in the graph.
Where people get burned
- Expecting GPU speed. It's scipy on the CPU; big
expandvalues on big masks stall the queue. If you need huge padding, feather instead, or accept the wait. - Shrinking leaves hard edges. Erode a mask and you get a crisp cliff, which reintroduces the seam you were trying to kill. Chain it into
FeatherMaskafterwards - grow for context, then feather to blend. - Forgetting the mask is your contract. Grow the mask, and the model now owns that extra ring of pixels too. More padding = more context but also more of the image subject to change. The 2026 consensus is 4–12px of blur and modest padding, not "grow it a mile."
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| mask | MASK | — | |
| expand | INT | 0-16384–16384 | — |
| tapered_corners | BOOLEAN | true | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| MASK | MASK | — |