Comfy-Org/ComfyUI · error · ValueError

File3DToSplat: invalid .ksplat compression level {level}

Error message

File3DToSplat: invalid .ksplat compression level {level}

What it means

Raised by _parse_ksplat_gaussian when the compression-level field at header offset 20 is not one of the supported levels keyed in _KSPLAT_COMPRESSION (levels 0, 1, 2). The level determines the per-splat record layout (float vs half precision, bucketed positions, uint8 SH), so an unknown level cannot be decoded.

Source

Thrown at comfy_extras/nodes_gaussian_splat.py:286

    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]

    parts = []
    base = 4096 + max_sections * 1024
    for s in range(max_sections):
        so = 4096 + s * 1024
        cnt = struct.unpack_from('<I', data, so + 0)[0]
        sec_max = struct.unpack_from('<I', data, so + 4)[0]
        bucket_size = struct.unpack_from('<I', data, so + 8)[0]
        bucket_count = struct.unpack_from('<I', data, so + 12)[0]
        block_size = struct.unpack_from('<f', data, so + 16)[0]
        bucket_store = struct.unpack_from('<H', data, so + 20)[0]
        scale_range = struct.unpack_from('<I', data, so + 24)[0] or default_range
        full_buckets = struct.unpack_from('<I', data, so + 32)[0]
        partial_buckets = struct.unpack_from('<I', data, so + 36)[0]
        sh_components = _KSPLAT_SH_COMPONENTS.get(struct.unpack_from('<H', data, so + 40)[0], 0)
        bytes_per_splat = bc + bs + br + bcol + sh_components * bshc
        meta_bytes = partial_buckets * 4

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Re-export the asset as .ply or .spz, which are fully supported.
  2. Regenerate the .ksplat with a library version writing level 0-2 (level 0 is what SplatToFile3D itself writes).
  3. If the file is valuable, verify its integrity against the source.

Example fix

null
Defensive patterns

Strategy: try-catch

Validate before calling

import struct
data = open(path, 'rb').read()
level = struct.unpack_from('<H', data, 20)[0]
if level not in (0, 1, 2):
    raise ValueError(f'ksplat compression level {level} unsupported (need 0-2)')

Type guard

def ksplat_level_supported(data: bytes) -> bool:
    return len(data) >= 22 and struct.unpack_from('<H', data, 20)[0] in (0, 1, 2)

Try / catch

try:
    result = _parse_ksplat_gaussian(data)
except ValueError as e:
    if 'compression level' in str(e):
        re_export_as_ply(path)
    else:
        raise

Prevention

When it happens

Trigger: File3DToSplat on a .ksplat that reports a compression level outside 0-2 — written by a newer/other variant of the SplatBuffer writer, or corrupted header bytes; also possible when a non-ksplat binary misdetects as ksplat and its bytes at offset 20 land on an unsupported value.

Common situations: Newer mkkellogg library adding level 3+; byte-level corruption of the 4096-byte header; wrong file fed to the node.

Related errors


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