Comfy-Org/ComfyUI · error · ValueError

MergeSplat: no gaussians to merge

Error message

MergeSplat: no gaussians to merge

What it means

Raised by _merge_gaussians when every element of the incoming gaussian list is None (after filtering). The merge helper is expected at least one real SPLAT to determine the output batch size and SH degree; with nothing connected it has no shape information and cannot construct a result. It is the internal backstop behind the MergeSplat node's own input check.

Source

Thrown at comfy_extras/nodes_gaussian_splat.py:1182

        if cls.hidden.unique_id:  # show the count inline on the node
            PromptServer.instance.send_progress_text(f"{count:,} splats", cls.hidden.unique_id)
        return IO.NodeOutput(splat, count)


def _pad_stack(items, n):
    # Stack a list of (Lᵢ, *tail) tensors into (B, n, *tail), zero-padding each row up to n.
    tail = items[0].shape[1:]
    out = items[0].new_zeros((len(items), n, *tail))
    for i, t in enumerate(items):
        out[i, :t.shape[0]] = t
    return out


def _merge_gaussians(gaussians: list) -> Types.SPLAT:
    # Concatenate SPLAT batches along the splat dimension (per item), padding SH to the highest degree.
    gs = [g for g in gaussians if g is not None]
    if not gs:
        raise ValueError("MergeSplat: no gaussians to merge")
    b = gs[0].positions.shape[0]
    for g in gs:
        if g.positions.shape[0] != b:
            raise ValueError(f"MergeSplat: batch size mismatch ({b} vs {g.positions.shape[0]}).")
    max_k = max(g.sh.shape[2] for g in gs)

    pos_b, scl_b, rot_b, op_b, sh_b, lengths = [], [], [], [], [], []
    for i in range(b):
        pos_i, scl_i, rot_i, op_i, sh_i = [], [], [], [], []
        for g in gs:
            end = _real_len(g, i)
            pos_i.append(g.positions[i, :end])
            scl_i.append(g.scales[i, :end])
            rot_i.append(g.rotations[i, :end])
            op_i.append(g.opacities[i, :end])
            sh = g.sh[i, :end]       # (end, K, 3)
            if sh.shape[1] < max_k:  # zero-pad lower-degree SH
                sh = torch.cat([sh, sh.new_zeros(sh.shape[0], max_k - sh.shape[1], sh.shape[2])], dim=1)

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Connect at least one splat input to MergeSplat.
  2. Unmute/unbypass the upstream nodes feeding the merge.
  3. If merging conditionally in code, filter Nones first and ensure the list is non-empty before calling.

Example fix

// before
merged = _merge_gaussians([None, None])

// after
gs = [g for g in splats if g is not None]
merged = _merge_gaussians(gs) if gs else None
Defensive patterns

Strategy: validation

Validate before calling

gs = [g for g in gaussians if g is not None]
if not gs:
    raise ValueError('MergeSplat: connect at least one splat')
merged = _merge_gaussians(gs)

Type guard

def has_any_splat(gaussians: list) -> bool:
    return any(g is not None for g in gaussians)

Try / catch

try:
    merged = _merge_gaussians(gs)
except ValueError as e:
    if 'no gaussians to merge' in str(e):
        merged = None  # or wire a default splat
    else:
        raise

Prevention

When it happens

Trigger: MergeSplat with all Autogrow inputs unconnected (caught one level up at line 1237), or a caller invoking _merge_gaussians directly with a list of Nones — e.g., optional upstream nodes that returned None on their empty path.

Common situations: Workflow branches where every upstream splat node was bypassed/muted; optional inputs that all evaluated to None; programmatic misuse of the private helper.

Related errors


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