BabylonJS/Babylon.js · error · Error
PLY mesh doesn't contain face informations.
Error message
PLY mesh doesn't contain face informations.
What it means
This error is thrown by the SPLAT file loader when a PLY file is parsed in Mesh mode but the parsed PLY data lacks face (index) information. The loader needs faces to build a regular mesh; a PLY that only contains vertex data (point cloud) cannot be converted into a mesh. It is thrown inside handlePLY during _parseAsync.
Source
Thrown at packages/dev/loaders/src/SPLAT/splatFileLoader.pure.ts:369
case Mode.PointCloud:
{
const pointcloud = new PointsCloudSystem("PointCloud", 1, scene);
if (SPLATFileLoader._BuildPointCloud(pointcloud, parsedPLY.data)) {
// eslint-disable-next-line github/no-then
await pointcloud.buildMeshAsync().then((mesh) => {
babylonMeshesArray.push(mesh);
});
} else {
pointcloud.dispose();
}
}
break;
case Mode.Mesh:
{
if (parsedPLY.faces) {
babylonMeshesArray.push(SPLATFileLoader._BuildMesh(scene, parsedPLY));
} else {
throw new Error("PLY mesh doesn't contain face informations.");
}
}
break;
default:
throw new Error("Unsupported Splat mode");
}
scene._blockEntityCollection = false;
this.applyAutoCameraLimits(SPLATFileLoader._ExtractSafeOrbitLimits(parsedPLY), scene);
resolve(babylonMeshesArray);
});
};
// Check for gzip (before SPZ V4) and NGSP (SPZ V4+) magic bytes to detect SPZ format
const isGZipped = u8[0] === 0x1f && u8[1] === 0x8b;
const isNGSP = u8[0] === 0x4e && u8[1] === 0x47 && u8[2] === 0x53 && u8[3] === 0x50;
if (!isGZipped && !isNGSP) {
return new Promise((resolve) => {
handlePLY(resolve);
View on GitHub (pinned to 0592b347b8)
Solutions
- Check the PLY header for a 'element face' entry; if absent, the file is a point cloud
- Switch the loader mode from Mode.Mesh to the point-cloud/splat mode appropriate for the file
- Re-export the PLY from the source tool with faces included if a mesh is truly required
- Convert the point cloud to a mesh with surface reconstruction before loading
Example fix
// before
loader.loadAsync("scene.ply"); // Mode.Mesh
// after
const loader = new SPLATFileLoader(Mode.Point); // or Splat mode for face-less PLY Defensive patterns
Strategy: validation
Validate before calling
const header = plyText.slice(0, plyText.indexOf('end_header'));
if (!/element face\s+\d+/.test(header)) {
// load as point cloud instead of mesh
} Type guard
function plyHasFaces(parsed: { faces?: unknown }): parsed is { faces: unknown[] } {
return Array.isArray(parsed.faces) && parsed.faces.length > 0;
} Try / catch
try {
await splatLoader.loadAsync(url, Mode.Mesh);
} catch (e) {
if (e instanceof Error && e.message.includes("face informations")) {
await splatLoader.loadAsync(url, Mode.Point);
} else throw e;
} Prevention
- Inspect the PLY header for 'element face' before choosing Mesh mode
- Use point/splat mode for splat or point-cloud PLY exports
- Pre-validate assets in a pipeline with glTF/PLY validators
- Standardize exporter settings to include faces when mesh mode is intended
When it happens
Trigger: Loading a .ply via SPLATFileLoader with mode set to Mode.Mesh while the PLY file has no 'face' element (e.g. vertex-only PLY or SPLAT/point-cloud PLY).
Common situations: Exporting a Gaussian splat / point cloud from tools like Polycam or Luma as PLY (these contain vertices + splat attributes but no faces), then loading it with Mesh mode instead of Point cloud or Splat mode; hand-authored PLY missing the face section.
Related errors
- Unsupported Splat mode
- No scene available to load asset container to
- No scene available to load animations to
- Unknown animation group loading mode value '${animationGroup
- Draco: Missing position attribute for encoding.
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/e29215d7d90aa42b.
Report an issue: GitHub.