{"record":{"id":"17bbd09872ea96cd","repo":"Comfy-Org/ComfyUI","slug":"file3dtosplat-ply-vertex-has-list-properties-uns","errorCode":null,"errorMessage":"File3DToSplat: PLY vertex has list properties (unsupported)","messagePattern":"File3DToSplat: PLY vertex has list properties \\(unsupported\\)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"comfy_extras/nodes_gaussian_splat.py","lineNumber":231,"sourceCode":"    if end < 0:\n        raise ValueError(\"File3DToSplat: not a PLY (missing end_header)\")\n    header = data[:end].decode('ascii', 'replace')\n    body = end + len(b'end_header')\n    body += 2 if data[body:body + 2] == b'\\r\\n' else 1\n    count, props, in_vertex = 0, [], False\n    for line in header.splitlines():\n        p = line.split()\n        if not p:\n            continue\n        if p[0] == 'format' and p[1] != 'binary_little_endian':\n            raise ValueError(f\"File3DToSplat: unsupported PLY format '{p[1]}' (need binary_little_endian)\")\n        if p[0] == 'element':\n            in_vertex = p[1] == 'vertex'\n            if in_vertex:\n                count = int(p[2])\n        elif p[0] == 'property' and in_vertex:\n            if p[1] == 'list':\n                raise ValueError(\"File3DToSplat: PLY vertex has list properties (unsupported)\")\n            props.append((p[2], '<' + _PLY_DTYPES[p[1]]))\n    arr = np.frombuffer(data, np.dtype(props), count=count, offset=body)\n    names = arr.dtype.names\n    c = lambda k: arr[k].astype(np.float32)\n    n = count\n\n    xyz = np.stack([c('x'), c('y'), c('z')], 1)\n    if 'scale_0' in names:\n        scale = np.exp(np.stack([c('scale_0'), c('scale_1'), c('scale_2')], 1))   # 3DGS stores log scale\n    else:\n        scale = np.full((n, 3), 0.01, np.float32)\n    if 'rot_0' in names:\n        rot = _norm_quat(np.stack([c('rot_0'), c('rot_1'), c('rot_2'), c('rot_3')], 1))   # wxyz\n    else:\n        rot = np.tile(np.array([1, 0, 0, 0], np.float32), (n, 1))\n    opacity = 1.0 / (1.0 + np.exp(-c('opacity'))) if 'opacity' in names else np.ones(n, np.float32)\n\n    if 'f_dc_0' in names:","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/Comfy-Org/ComfyUI/blob/1c6d8d45b3693bfbb32385b410d813a7fd6be216/comfy_extras/nodes_gaussian_splat.py#L213-L249","documentation":"Raised by _parse_ply_gaussian when a vertex-element property is declared as 'property list ...' inside the vertex element. The parser maps each vertex property to one fixed-size numpy dtype field, and list properties have per-vertex variable length, which cannot be represented in a packed record. Face lists (in the face element) are fine; the check only applies to the vertex element actually parsed.","triggerScenarios":"File3DToSplat on a PLY whose vertex element contains list properties, e.g. custom exporters writing per-vertex index lists, variable-length extra attributes, or files produced by tools that attach list-typed custom data to vertices.","commonSituations":"Non-3DGS PLYs from niche tools; a corrupted header where a fixed property line got mangled into a list declaration; hand-generated PLY headers with wrong property syntax.","solutions":["Re-export the file without per-vertex list properties (standard 3DGS PLY writers never emit them).","Strip the offending list properties with a conversion tool (plyfile) and rewrite a clean binary PLY.","If you generated the file yourself, fix the writer to emit only scalar vertex properties."],"exampleFix":"null","handlingStrategy":"validation","validationCode":"header = data[:data.find(b'end_header')].decode('ascii', 'replace')\nin_vertex = False\nfor line in header.splitlines():\n    p = line.split()\n    if not p:\n        continue\n    if p[0] == 'element':\n        in_vertex = p[1] == 'vertex'\n    elif p[0] == 'property' and in_vertex and p[1] == 'list':\n        raise ValueError('vertex list properties unsupported; re-export the PLY')","typeGuard":"def ply_vertex_scalar_only(data: bytes) -> bool:\n    end = data.find(b'end_header')\n    if end < 0:\n        return False\n    in_vertex = False\n    for line in data[:end].decode('ascii', 'replace').splitlines():\n        p = line.split()\n        if p and p[0] == 'element':\n            in_vertex = p[1] == 'vertex'\n        elif p and p[0] == 'property' and in_vertex and p[1] == 'list':\n            return False\n    return True","tryCatchPattern":"try:\n    result = _parse_ply_gaussian(data)\nexcept ValueError as e:\n    if 'list properties' in str(e):\n        strip_vertex_lists_with_plyfile(path)\n    else:\n        raise","preventionTips":["Use mainstream 3DGS PLY writers; they never emit vertex list properties.","Validate the header shape when accepting PLYs from unknown tools."],"tags":["gaussian-splatting","ply","file-format","unsupported-feature"],"backgroundTag":null,"analyzedSha":"1c6d8d45b3693bfbb32385b410d813a7fd6be216","analyzedAt":"2026-08-14T19:37:18.893Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}