Comfy-Org/ComfyUI · error · ValueError

File3DToSplat: .splat size is not a multiple of 32 bytes

Error message

File3DToSplat: .splat size is not a multiple of 32 bytes

What it means

Raised by _parse_splat_gaussian when parsing antimatter15-format .splat data whose byte length is not a multiple of 32. Each splat is a fixed 32-byte record (3 f32 position + 3 f32 scale + 4 u8 RGBA + 4 u8 quantized quaternion), so any remainder indicates a truncated, corrupted, or non-.splat file.

Source

Thrown at comfy_extras/nodes_gaussian_splat.py:269

        rest = sorted((k for k in names if k.startswith('f_rest_')), key=lambda s: int(s.split('_')[-1]))
        if rest:
            r = np.stack([c(k) for k in rest], 1)                                 # (N, 3*(K-1)) channel-major
            kk = r.shape[1] // 3 + 1
            r = r.reshape(n, 3, kk - 1).transpose(0, 2, 1)                        # -> (N, K-1, 3)
            sh = np.concatenate([dc[:, None, :], r], 1)
        else:
            sh = dc[:, None, :]
    elif 'red' in names:
        sh = _rgb_to_sh_dc(np.stack([c('red'), c('green'), c('blue')], 1) / 255.0)
    else:
        sh = np.zeros((n, 1, 3), np.float32)
    return xyz, scale, rot, opacity, sh


def _parse_splat_gaussian(data: bytes):
    # antimatter15 .splat: 32-byte records (f32 xyz, f32 scale, u8 rgba, u8 quat as (b-128)/128 wxyz).
    if len(data) % 32 != 0:
        raise ValueError("File3DToSplat: .splat size is not a multiple of 32 bytes")
    rec = np.frombuffer(data, np.dtype([('xyz', '<f4', 3), ('scale', '<f4', 3),
                                        ('rgba', 'u1', 4), ('quat', 'u1', 4)]))
    rgba = rec['rgba'].astype(np.float32) / 255.0
    rot = _norm_quat((rec['quat'].astype(np.float32) - 128.0) / 128.0)            # wxyz
    return (rec['xyz'].astype(np.float32), rec['scale'].astype(np.float32), rot,
            rgba[:, 3].copy(), _rgb_to_sh_dc(rgba[:, :3]))


def _parse_ksplat_gaussian(data: bytes):
    # mkkellogg SplatBuffer: 4096-byte header, N section headers, then per-section splat data. Supports
    # levels 0 (float) / 1 (half + bucketed positions) / 2 (half, uint8 SH). SH is skipped (base color kept).
    if data[0] != 0:
        raise ValueError(f"File3DToSplat: unsupported .ksplat version {data[0]}.{data[1]}")
    max_sections = struct.unpack_from('<I', data, 4)[0]
    level = struct.unpack_from('<H', data, 20)[0]
    if level not in _KSPLAT_COMPRESSION:
        raise ValueError(f"File3DToSplat: invalid .ksplat compression level {level}")
    bc, bs, br, bcol, bshc, default_range = _KSPLAT_COMPRESSION[level]

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Verify the file size: size % 32 must be 0 and match the expected splat count times 32.
  2. Re-download or regenerate the .splat from its source.
  3. Confirm the file is actually antimatter15 .splat format, not another splat flavor renamed to .splat.

Example fix

null
Defensive patterns

Strategy: validation

Validate before calling

data = open(path, 'rb').read()
if data[:3] == b'ply' or data[:2] == b'\x1f\x8b' or (len(data) >= 2 and data[0] == 0 and data[1] >= 1):
    pass  # other formats
elif len(data) % 32 != 0:
    raise ValueError(f'{path} is not a valid 32-byte-record .splat (size {len(data)})')

Type guard

def is_splat_v1(data: bytes) -> bool:
    return (len(data) > 0 and len(data) % 32 == 0
            and data[:3] != b'ply' and data[:2] != b'\x1f\x8b')

Try / catch

try:
    result = _parse_splat_gaussian(data)
except ValueError as e:
    if 'multiple of 32 bytes' in str(e):
        re_fetch_or_reconvert(path)
    else:
        raise

Prevention

When it happens

Trigger: File3DToSplat on data that failed the ply/spz/ksplat signature checks but whose length happens not to divide by 32 — typically a genuinely truncated or corrupted .splat, or an arbitrary binary file with an unlucky length. Also a partially uploaded/downloaded .splat.

Common situations: Truncated download of a .splat; file cut off mid-write; feeding a random binary blob to the node hoping it is a splat.

Related errors


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