{"record":{"id":"117eed61f787158b","repo":"Comfy-Org/ComfyUI","slug":"mergesplat-batch-size-mismatch-b-vs-g-positio","errorCode":null,"errorMessage":"MergeSplat: batch size mismatch ({b} vs {g.positions.shape[0]}).","messagePattern":"MergeSplat: batch size mismatch \\((.+?) vs (.+?)\\)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"comfy_extras/nodes_gaussian_splat.py","lineNumber":1186,"sourceCode":"\ndef _pad_stack(items, n):\n    # Stack a list of (Lᵢ, *tail) tensors into (B, n, *tail), zero-padding each row up to n.\n    tail = items[0].shape[1:]\n    out = items[0].new_zeros((len(items), n, *tail))\n    for i, t in enumerate(items):\n        out[i, :t.shape[0]] = t\n    return out\n\n\ndef _merge_gaussians(gaussians: list) -> Types.SPLAT:\n    # Concatenate SPLAT batches along the splat dimension (per item), padding SH to the highest degree.\n    gs = [g for g in gaussians if g is not None]\n    if not gs:\n        raise ValueError(\"MergeSplat: no gaussians to merge\")\n    b = gs[0].positions.shape[0]\n    for g in gs:\n        if g.positions.shape[0] != b:\n            raise ValueError(f\"MergeSplat: batch size mismatch ({b} vs {g.positions.shape[0]}).\")\n    max_k = max(g.sh.shape[2] for g in gs)\n\n    pos_b, scl_b, rot_b, op_b, sh_b, lengths = [], [], [], [], [], []\n    for i in range(b):\n        pos_i, scl_i, rot_i, op_i, sh_i = [], [], [], [], []\n        for g in gs:\n            end = _real_len(g, i)\n            pos_i.append(g.positions[i, :end])\n            scl_i.append(g.scales[i, :end])\n            rot_i.append(g.rotations[i, :end])\n            op_i.append(g.opacities[i, :end])\n            sh = g.sh[i, :end]       # (end, K, 3)\n            if sh.shape[1] < max_k:  # zero-pad lower-degree SH\n                sh = torch.cat([sh, sh.new_zeros(sh.shape[0], max_k - sh.shape[1], sh.shape[2])], dim=1)\n            sh_i.append(sh)\n        pos_b.append(torch.cat(pos_i))\n        scl_b.append(torch.cat(scl_i))\n        rot_b.append(torch.cat(rot_i))","sourceCodeStart":1168,"sourceCodeEnd":1204,"githubUrl":"https://github.com/Comfy-Org/ComfyUI/blob/1c6d8d45b3693bfbb32385b410d813a7fd6be216/comfy_extras/nodes_gaussian_splat.py#L1168-L1204","documentation":"Raised by _merge_gaussians when the input SPLATs disagree on batch size (positions.shape[0]). Merge is defined per batch item — it concatenates each item's gaussians across inputs and pads SH to the max degree — so every input must carry the same number of items. The first input's batch size is the reference; any deviation raises with both values.","triggerScenarios":"Merging a splat with batch size 1 against one with batch size 4 (e.g., one decoded from a batched latent, another loaded from a single-item file via File3DToSplat); mixing sources with different item counts in MergeSplat.","commonSituations":"One input from a batched generation node and another from a single loaded file; upstream nodes that changed batch handling after a workflow edit.","solutions":["Make all merged splats share a batch size: select the same batch item (slice/re-batch) before merging.","If one input is single-item, expand or pick matching items so shapes align.","Check each upstream node's batch dimension (positions.shape[0]) and align them."],"exampleFix":"# before: batch sizes 1 and 4\nmerged = _merge_gaussians([splat_b1, splat_b4])\n\n# after: align to the same item count\nmerged = _merge_gaussians([splat_b1, splat_b4[0:1]])","handlingStrategy":"validation","validationCode":"sizes = {g.positions.shape[0] for g in gs}\nif len(sizes) > 1:\n    raise ValueError(f'MergeSplat batch mismatch: {sizes}; align batch sizes first')\nmerged = _merge_gaussians(gs)","typeGuard":"def same_batch_size(gs: list) -> bool:\n    return len({g.positions.shape[0] for g in gs}) == 1","tryCatchPattern":"try:\n    merged = _merge_gaussians(gs)\nexcept ValueError as e:\n    if 'batch size mismatch' in str(e):\n        b = gs[0].positions.shape[0]\n        gs = [g[:b] for g in gs]  # align to first input's batch\n        merged = _merge_gaussians(gs)\n    else:\n        raise","preventionTips":["Select matching batch items before merging (File3DToSplat yields batch size 1).","Assert equal positions.shape[0] on all merge inputs in the workflow."],"tags":["gaussian-splatting","shape-mismatch","batch","merge"],"backgroundTag":null,"analyzedSha":"1c6d8d45b3693bfbb32385b410d813a7fd6be216","analyzedAt":"2026-08-14T19:37:18.893Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}