Comfy-Org/ComfyUI · error · ValueError
File3DToSplat: could not determine splat format from content
Error message
File3DToSplat: could not determine splat format from contents
What it means
Raised by _detect_splat_format when the input bytes match none of the four known signatures: 'ply' magic, gzip magic (\x1f\x8b), a ksplat 0.x header (byte0 == 0, byte1 >= 1), or a length divisible by 32 (antimatter15 .splat). File3DToSplat sniffs content rather than trusting the extension, so this means the payload is not recognizable as any supported splat format.
Source
Thrown at comfy_extras/nodes_gaussian_splat.py:406
w = np.sqrt(np.clip(1.0 - (xq ** 2).sum(1), 0, None))
rot = _norm_quat(np.concatenate([w[:, None], xq], 1)) # wxyz
return xyz, scale, rot, alpha, _rgb_to_sh_dc(rgb)
_GAUSSIAN_PARSERS = {"ply": _parse_ply_gaussian, "splat": _parse_splat_gaussian,
"ksplat": _parse_ksplat_gaussian, "spz": _parse_spz_gaussian}
def _detect_splat_format(data: bytes) -> str:
if data[:3] == b'ply':
return "ply"
if data[:2] == b'\x1f\x8b': # gzip -> spz
return "spz"
if len(data) >= 2 and data[0] == 0 and data[1] >= 1: # ksplat version 0.x header
return "ksplat"
if len(data) % 32 == 0:
return "splat"
raise ValueError("File3DToSplat: could not determine splat format from contents")
def _gaussian_item(g: Types.SPLAT, i: int, device):
# Slice batch item i to its real length, as float32 torch tensors on `device` (SH DC -> base RGB).
end = _real_len(g, i)
to = lambda a: a.to(device=device, dtype=torch.float32)
xyz = to(g.positions[i, :end])
rgb = (to(g.sh[i, :end, 0, :]) * _C0 + 0.5).clamp(0, 1)
opacity = to(g.opacities[i, :end]).reshape(-1)
scale = to(g.scales[i, :end])
rot = to(g.rotations[i, :end])
return xyz, rgb, opacity, scale, rot
def _quat_to_mat(q):
# q: (N, 4) wxyz, normalized -> (N, 3, 3)
q = q / q.norm(dim=-1, keepdim=True).clamp_min(1e-12)
w, x, y, z = q.unbind(-1)View on GitHub (pinned to 1c6d8d45b3)
Solutions
- Confirm the file is one of: PLY (binary_little_endian 3DGS), antimatter15 .splat, mkkellogg .ksplat v0.x, or Niantic .spz.
- Re-download/regenerate the file; verify magic bytes with a hex editor (70 6c 79 / 1f 8b / 00 xx).
- Convert the asset from its source format to one of the supported ones before loading.
Example fix
null
Defensive patterns
Strategy: validation
Validate before calling
def sniff_splat_format(data: bytes):
if data[:3] == b'ply':
return 'ply'
if data[:2] == b'\x1f\x8b':
return 'spz'
if len(data) >= 2 and data[0] == 0 and data[1] >= 1:
return 'ksplat'
if len(data) % 32 == 0:
return 'splat'
return None
fmt = sniff_splat_format(open(path, 'rb').read())
if fmt is None:
raise ValueError(f'{path} is not a recognized splat format') Type guard
def is_supported_splat_file(data: bytes) -> bool:
return sniff_splat_format(data) is not None Try / catch
try:
fmt = _detect_splat_format(data)
except ValueError as e:
if 'could not determine' in str(e):
convert_asset_from_source(path)
else:
raise Prevention
- Check magic bytes before loading unknown splat files.
- Convert obj/glb/las and other 3D formats in a preprocessing step; File3DToSplat only reads ply/splat/ksplat/spz.
When it happens
Trigger: File3DToSplat on an arbitrary binary, a non-splat 3D format (obj/glb/las), an empty-ish or misaligned file whose length is not a multiple of 32, or a corrupted splat whose magic bytes were damaged.
Common situations: Wrong file connected to the node; a model file from another pipeline; corrupt download that lost its magic bytes; a .splat truncated so the length no longer divides by 32.
Related errors
- File3DToSplat: not a PLY (missing end_header)
- File3DToSplat: unsupported PLY format '{p[1]}' (need binary_
- File3DToSplat: PLY vertex has list properties (unsupported)
- File3DToSplat: unsupported .ksplat version {data[0]}.{data[1
- File3DToSplat: invalid .ksplat compression level {level}
AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14).
Data as JSON: /api/errors/8a8df750246448fb.
Report an issue: GitHub.