Comfy-Org/ComfyUI · error · ValueError

MergeSplat: connect at least one splat.

Error message

MergeSplat: connect at least one splat.

What it means

Raised by MergeSplat.execute when the Autogrow 'splats' input contains no connected values (all entries None or the input is empty). The node needs at least one SPLAT to produce an output, so it fails fast rather than emitting a meaningless empty splat. This is the user-facing check; the deeper _merge_gaussians has its own equivalent guard.

Source

Thrown at comfy_extras/nodes_gaussian_splat.py:1237

    def define_schema(cls):
        # Autogrow: a splat0/splat1/... input list that grows a fresh slot as you connect splats.
        splats = IO.Autogrow.TemplatePrefix(IO.Splat.Input("splat"), prefix="splat", min=2, max=32)
        return IO.Schema(
            node_id="MergeSplat",
            display_name="Merge Splats",
            search_aliases=["union splat", "densify gaussian", "combine splat", "merge gaussian"],
            category="3d/splat",
            description="Concatenate any number of gaussian splats into one. Unioning several decodes of the same "
                        "latent at different seeds densifies the surface, this can improve surface quality when meshing.",
            inputs=[IO.Autogrow.Input("splats", template=splats)],
            outputs=[IO.Splat.Output(display_name="splat")],
        )

    @classmethod
    def execute(cls, splats: IO.Autogrow.Type) -> IO.NodeOutput:
        gs = [v for v in splats.values() if v is not None]
        if not gs:
            raise ValueError("MergeSplat: connect at least one splat.")
        return IO.NodeOutput(_merge_gaussians(gs))


def _inverse_covariance(scale, quat):
    # Per-splat Sigma^-1 = R diag(1/s^2) R^T. scale (N,3) linear std, quat (N,4) wxyz -> (N,3,3).
    q = quat / quat.norm(dim=1, keepdim=True).clamp_min(1e-12)
    w, x, y, z = q.unbind(-1)
    R = torch.stack([
        1 - 2 * (y * y + z * z), 2 * (x * y - w * z), 2 * (x * z + w * y),
        2 * (x * y + w * z), 1 - 2 * (x * x + z * z), 2 * (y * z - w * x),
        2 * (x * z - w * y), 2 * (y * z + w * x), 1 - 2 * (x * x + y * y),
    ], dim=1).reshape(-1, 3, 3)
    inv_s2 = 1.0 / scale.clamp_min(1e-8) ** 2                       # (N, 3)
    return torch.einsum("nij,nj,nkj->nik", R, inv_s2, R)


def _splat_density(xyz, opacity, scale, quat, rgb, res, kernel, device, color_sharpen=1.0, chunk=4096, progress=None,
                   col_dtype=torch.float16):

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Connect at least one splat output to a 'splats' input of the node.
  2. Unmute/unbypass the upstream splat nodes.
  3. Autogrow sockets accept any count >= 0, so make sure at least one wire actually carries a SPLAT.

Example fix

null
Defensive patterns

Strategy: validation

Validate before calling

gs = [v for v in splats.values() if v is not None]
if not gs:
    raise ValueError('MergeSplat: connect at least one splat.')

Type guard

def merge_inputs_ready(splats) -> bool:
    return any(v is not None for v in splats.values())

Try / catch

try:
    out = MergeSplat().execute(splats)
except ValueError as e:
    if 'connect at least one splat' in str(e):
        skip_merge()
    else:
        raise

Prevention

When it happens

Trigger: Executing a MergeSplat node with zero connected splat wires; all its inputs muted/bypassed upstream so they deliver None; a workflow template instantiated without wiring the merge inputs.

Common situations: Building a densify-with-multiple-seeds workflow and running it before connecting the decode outputs; bypassing every upstream producer during debugging.

Related errors


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