Comfy-Org/ComfyUI · error · ValueError

Compositor supports at most {MAX_LAYERS} layers, got {len(fr

Error message

Compositor supports at most {MAX_LAYERS} layers, got {len(frames)}

What it means

After collecting layer frames from a LAYERS document, the compositor enforces MAX_LAYERS = 50 and refuses longer lists with this message. This bounds the per-composite numpy canvas work and UI complexity; the count is of frames that survived filtering (valid raster tensors), not of all raw document entries.

Source

Thrown at comfy_extras/nodes_compositor.py:124

            frames.append({
                "tensor": image[index : index + 1],
                "mask": _item_mask_frame(item.get("mask"), index),
                "name": item.get("name") if isinstance(item.get("name"), str) else None,
                "x": _int(item.get("x"), 0),
                "y": _int(item.get("y"), 0),
                "w": width if width > 0 else int(image.shape[2]),
                "h": height if height > 0 else int(image.shape[1]),
                "rotation": float(rotation)
                if isinstance(rotation, (int, float)) and not isinstance(rotation, bool)
                else 0.0,
                "opacity": item.get("opacity", 1.0),
                "blend": item.get("blend_mode", "normal"),
                "visible": item.get("visible", True),
                "flip_h": bool(item.get("flip_h", False)),
                "flip_v": bool(item.get("flip_v", False)),
            })
    if len(frames) > MAX_LAYERS:
        raise ValueError(
            f"Compositor supports at most {MAX_LAYERS} layers, got {len(frames)}"
        )
    return frames


def frame_alpha(
    tensor: torch.Tensor, mask: torch.Tensor | None
) -> torch.Tensor | None:
    alpha = tensor[:1, :, :, 3] if tensor.shape[-1] == 4 else None
    if mask is None:
        return alpha
    h, w = tensor.shape[1], tensor.shape[2]
    m = mask[:1].to(device=tensor.device, dtype=torch.float32)
    if m.shape[1] != h or m.shape[2] != w:
        m = torch.nn.functional.interpolate(
            m.unsqueeze(1), size=(h, w), mode="bilinear"
        ).squeeze(1)
    inv = torch.clamp(1.0 - m, 0.0, 1.0)

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Reduce the document to at most 50 raster layers — drop invisible or fully occluded layers first.
  2. Split the work into multiple compositor nodes (e.g. 2 x 30 layers) and composite their outputs together.
  3. Pre-flatten groups of layers into single raster images upstream to shrink the layer count.

Example fix

# before
doc["layers"] = all_80_layers
# after
doc["layers"] = [l for l in all_80_layers if l.get("visible", True)][:50]
Defensive patterns

Strategy: validation

Validate before calling

MAX_LAYERS = 50
def clamp_layers(doc, keep_visible_first=True):
    layers = doc.get("layers") or []
    if keep_visible_first:
        layers = sorted(layers, key=lambda l: not l.get("visible", True))
    doc = dict(doc, layers=layers[:MAX_LAYERS])
    return doc

Prevention

When it happens

Trigger: A LAYERS document (or aggregated documents) whose valid raster layers total more than 50 — e.g. 60 image layers each carrying a torch.Tensor image. Non-dict items and items without tensor images are skipped before the count, so it takes 51 real layers to trip it.

Common situations: Programmatically generated documents (one layer per detection, tile, or animation frame) that scale past 50; concatenating multiple documents' layers lists into one composite.

Related errors


AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14). Data as JSON: /api/errors/f352a02832276220. Report an issue: GitHub.